背景
目前 dubbo-go 的泛化调用已经支持了核心功能(Map 序列化、Gson 序列化、Triple 协议等),但在实际使用中发现还有一些功能缺失,影响了跨语言调用的体验。
经过对比 Java dubbo 的实现,整理出以下需要补充的功能点。
现状
| 功能 |
Java dubbo |
dubbo-go |
Map 序列化 (generic=true) |
支持 |
支持 |
| Gson 序列化 |
支持 |
支持 |
| Consumer/Provider Filter |
支持 |
支持 |
| Triple 协议支持 |
支持 |
支持 |
| GenericException 异常 |
支持 |
缺失 |
| 响应自动反序列化 |
支持 |
缺失 |
| generic.include.class 配置 |
支持 |
缺失 |
| protobuf-json 序列化 |
支持 |
代码有了但没接入 |
| Bean 序列化 |
支持 |
缺失 |
需要补充的功能
1. GenericException 异常处理
当 dubbo-go 调用 Java 服务时,如果 Java 端抛出业务异常,目前只能拿到一个字符串错误信息,原始的异常类型丢了。
比如 Java 端抛出 UserNotFoundException,dubbo-go 这边只能拿到 "用户不存在" 这个字符串,没办法知道这是什么类型的异常,也就没法做针对性的处理。
如果能拿到完整的异常信息就好了:
type GenericException struct {
ExceptionClass string // 比如 "com.example.UserNotFoundException"
ExceptionMessage string // 比如 "用户不存在"
}
可以参考 Java dubbo 的 GenericException.java:
dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java
2. 响应自动反序列化
现在泛化调用返回的是 map[string]any,每次都要自己手动转成结构体,写起来挺烦的:
result, _ := genericService.Invoke(ctx, "getUser", []string{"String"}, []any{"123"})
m := result.(map[string]any)
user := &User{
Name: m["name"].(string),
Age: int(m["age"].(float64)),
}
要是能直接反序列化到结构体就方便多了:
var user User
genericService.InvokeWithType(ctx, "getUser", []string{"String"}, []any{"123"}, &user)
改动点在 filter/generic/filter.go 的 OnResponse 方法。
3. generic.include.class 配置
Java dubbo 有个 generic.include.class 配置,控制序列化时要不要带 class 字段:
true:{"class":"com.example.User", "name":"张三"}
false:{"name":"张三"}
如果 Java 端配置了 generic.include.class=false,dubbo-go 得能正确处理才行。
改动点:
common/constant/key.go 加个常量
filter/generic/generalizer/map.go 读配置控制行为
4. protobuf-json 序列化接入
ProtobufJsonGeneralizer 代码已经写好了(在 filter/generic/generalizer/protobuf_json.go),Triple 协议层也支持了,但 Filter 层没接上,导致实际用不了。
问题在 filter/generic/util.go:
// isGeneric 只认 "true",不认 protobuf-json
func isGeneric(generic string) bool {
lowerGeneric := strings.ToLower(generic)
return lowerGeneric == constant.GenericSerializationDefault
}
// getGeneralizer 没有 protobuf-json 的 case
func getGeneralizer(generic string) (g generalizer.Generalizer) {
switch strings.ToLower(generic) {
case constant.GenericSerializationDefault:
g = generalizer.GetMapGeneralizer()
case constant.GenericSerializationGson:
g = generalizer.GetGsonGeneralizer()
// 缺少 protobuf-json
default:
g = generalizer.GetMapGeneralizer()
}
return
}
改动点:
filter/generic/util.go 的 isGeneric 和 getGeneralizer 加上 protobuf-json 的支持
5. Bean 序列化
Java dubbo 支持 generic=bean 序列化,用 JavaBeanDescriptor 来描述对象。如果要调用的 Java 服务配了 generic=bean,现在 dubbo-go 处理不了。
可以参考 Java dubbo 的实现:
dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanDescriptor.java
相关文件
dubbo-go 需要改动的文件
| 功能 |
文件 |
| GenericException |
filter/generic/exception.go (新建) |
| GenericException |
filter/generic/service_filter.go |
| 响应反序列化 |
filter/generic/filter.go |
| include.class |
common/constant/key.go |
| include.class |
filter/generic/generalizer/map.go |
| protobuf-json |
filter/generic/util.go |
| Bean 序列化 |
filter/generic/generalizer/bean.go (新建) |
Java dubbo 参考文件
| 功能 |
文件 |
| GenericException |
dubbo-common/.../rpc/service/GenericException.java |
| 响应处理 |
dubbo-rpc/.../filter/GenericImplFilter.java |
| include.class |
dubbo-common/.../utils/PojoUtils.java |
| Bean 序列化 |
dubbo-common/.../beanutil/JavaBeanDescriptor.java |
背景
目前 dubbo-go 的泛化调用已经支持了核心功能(Map 序列化、Gson 序列化、Triple 协议等),但在实际使用中发现还有一些功能缺失,影响了跨语言调用的体验。
经过对比 Java dubbo 的实现,整理出以下需要补充的功能点。
现状
generic=true)需要补充的功能
1. GenericException 异常处理
当 dubbo-go 调用 Java 服务时,如果 Java 端抛出业务异常,目前只能拿到一个字符串错误信息,原始的异常类型丢了。
比如 Java 端抛出
UserNotFoundException,dubbo-go 这边只能拿到"用户不存在"这个字符串,没办法知道这是什么类型的异常,也就没法做针对性的处理。如果能拿到完整的异常信息就好了:
可以参考 Java dubbo 的
GenericException.java:dubbo-common/src/main/java/org/apache/dubbo/rpc/service/GenericException.java2. 响应自动反序列化
现在泛化调用返回的是
map[string]any,每次都要自己手动转成结构体,写起来挺烦的:要是能直接反序列化到结构体就方便多了:
改动点在
filter/generic/filter.go的OnResponse方法。3. generic.include.class 配置
Java dubbo 有个
generic.include.class配置,控制序列化时要不要带class字段:true:{"class":"com.example.User", "name":"张三"}false:{"name":"张三"}如果 Java 端配置了
generic.include.class=false,dubbo-go 得能正确处理才行。改动点:
common/constant/key.go加个常量filter/generic/generalizer/map.go读配置控制行为4. protobuf-json 序列化接入
ProtobufJsonGeneralizer代码已经写好了(在filter/generic/generalizer/protobuf_json.go),Triple 协议层也支持了,但 Filter 层没接上,导致实际用不了。问题在
filter/generic/util.go:改动点:
filter/generic/util.go的isGeneric和getGeneralizer加上 protobuf-json 的支持5. Bean 序列化
Java dubbo 支持
generic=bean序列化,用JavaBeanDescriptor来描述对象。如果要调用的 Java 服务配了generic=bean,现在 dubbo-go 处理不了。可以参考 Java dubbo 的实现:
dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanDescriptor.java相关文件
dubbo-go 需要改动的文件
filter/generic/exception.go(新建)filter/generic/service_filter.gofilter/generic/filter.gocommon/constant/key.gofilter/generic/generalizer/map.gofilter/generic/util.gofilter/generic/generalizer/bean.go(新建)Java dubbo 参考文件
dubbo-common/.../rpc/service/GenericException.javadubbo-rpc/.../filter/GenericImplFilter.javadubbo-common/.../utils/PojoUtils.javadubbo-common/.../beanutil/JavaBeanDescriptor.java