原生grpc迁移至dubbo tri协议问题汇总
tri协议,中文异常乱码
Filter中抛出错误:
throw new BusinessException("错误的token");
得到结果:中文乱码
{
"error": "13 INTERNAL: Exception in invoker chain :???token"
}
tri协议,在异常中加入无意义内容(Exception in invoker chain :),导致前端不方便提示异常
public abstract class AbstractServerStream extends AbstractStream implements Stream {
public void execute(Runnable runnable) {
try {
super.execute(() -> {
try {
runnable.run();
} catch (Throwable t) {
LOGGER.error("Exception processing triple message", t);
transportError(GrpcStatus.fromCode(GrpcStatus.Code.INTERNAL)
.withDescription("Exception in invoker chain :" + t.getMessage())
.withCause(t));
}
});
} catch (RejectedExecutionException e) {
LOGGER.error("Provider's thread pool is full", e);
transportError(GrpcStatus.fromCode(GrpcStatus.Code.RESOURCE_EXHAUSTED)
.withDescription("Provider's thread pool is full"));
} catch (Throwable t) {
LOGGER.error("Provider submit request to thread pool error ", t);
transportError(GrpcStatus.fromCode(GrpcStatus.Code.INTERNAL)
.withCause(t)
.withDescription("Provider's error"));
}
}
}
@yl-yue Only RpcException can be thrown in the filter. Please provide an example of garbled characters. I think the second problem needs to be fixed.
@yl-yue
- tri 协议由于使用了 pb 序列化,对异常的序列化支持不好,同时对于异常使用了 http2的 header 进行传输,header 的大小有限制,不能够将异常进行序列化放入 header 中,故不支持完整的异常重放。
- 由于 http2 header 的限制,内容只支持 AsciiString,对于其他编码建议进行 base64后放入 header
- 如果想实现上述功能,建议参考 #8363
@CrazyHZM
异常中添加前置内容不属于 bug,只为定位问题,不应该做为业务异常处理或显示
异常中添加前置内容不属于 bug,只为定位问题,不应该做为业务异常处理或显示
This seems to throw an exception only when the behavior in the framework does not meet expectations. If this is the case, there is no problem here.
@EarthChen Can you add a document about the above-mentioned custom exception handling to facilitate subsequent dissemination?
异常中添加前置内容不属于 bug,只为定位问题,不应该做为业务异常处理或显示
This seems to throw an exception only when the behavior in the framework does not meet expectations. If this is the case, there is no problem here.
@EarthChen Can you add a document about the above-mentioned custom exception handling to facilitate subsequent dissemination?
ok,I'll do that in the near future.
@yl-yue Only RpcException can be thrown in the filter. Please provide an example of garbled characters. I think the second problem needs to be fixed.
filter throw exception:
@Activate(group = CommonConstants.PROVIDER)
public class TokenFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation inv) {
throw new RpcException("错误的token");
}
}
result:
{
"error": "13 INTERNAL: Exception in invoker chain :???token"
}
Whether a Filter throw Exception or another throw exception, any message containing Chinese will be interpreted as garbled(?)
@yl-yue
- tri 协议由于使用了 pb 序列化,对异常的序列化支持不好,同时对于异常使用了 http2的 header 进行传输,header 的大小有限制,不能够将异常进行序列化放入 header 中,故不支持完整的异常重放。
- 由于 http2 header 的限制,内容只支持 AsciiString,对于其他编码建议进行 base64后放入 header
- 如果想实现上述功能,建议参考 [Dubbo 3.0.1] use triple protocol cant return real exception #8363
回复与新疑惑
- 测试了 #8363 issues中提供的demo,最终的结果只是把
13 INTERNAL换成了2 UNKNOWN,不过Exception in invoker chain :这串dubbo定义的前缀没了,但中文乱码任然存在。 - 关于是
2 UNKNOWN还是13 INTERNAL,更适合携带业务异常,或许dubbo可以从规范入手,做个规约说明。 - 如果中文需要经过base64编码,这样对前端调试解析并不友好,意味着需要base64解码。
更多想法
站在我现在的角度,其实我只粗浅的觉得,dubbo tri协议最大的亮点是,不需要写下面这两行糟糕的代码:
responseObserver.onNext();
responseObserver.onCompleted();
那么是否可以考虑,dubbo tri协议是对grpc协议的缺陷或不优雅进行补足,并做增强,而不是改变,导致不能平滑迁移(只改controller层)
如果中文需要经过base64编码,这样对前端调试解析并不友好,意味着需要base64解码。
- base64是因为grpc header 规定了-bin 的都要 base64,当然你可以 url encode,只不过 base64兼容更广
dubbo定义的前缀没了,但中文乱码任然存在。
- 乱码这个问题,将在下个版本修复它
关于是2 UNKNOWN还是13 INTERNAL,更适合携带业务异常,或许dubbo可以从规范入手,做个规约说明
- grpc 除了框架异常,其他均是 unknown,所以这里为了保持一致
- 总得来说,如果需要业务异常进行处理,建议增加 attach 使用 filter 在两端进行异常转换,不要使用 grpc-message
dubbo tri协议是对grpc协议的缺陷或不优雅进行补足,并做增强,而不是改变,导致不能平滑迁移(只改controller层)
- 对于 unary 方法,dubbo 中不写
onNext和onCompleted是为了兼容 dubbo2,并不是为了兼容 grpc 的写法。 - tri 和 grpc 的兼容只限于互通
@EarthChen 感谢解答,谢谢!
问题一:tri协议,中文异常乱码
答案:会在下个版本中得到解决
问题二:tri协议,在异常中加入无意义内容(Exception in invoker chain :),导致前端不方便提示异常
- 答案?:需要将
13 INTERNAL异常,转换为2 UNKNOWN异常,间接解决? - 答案?:会在下个版本中得到解决,移除
Exception in invoker chain :内容(或可配置开关)
那么问题二的答案是?
总得来说,如果需要业务异常进行处理,建议增加 attach 使用 filter 在两端进行异常转换,不要使用 grpc-message
- 主要的问题在于我们的前端web与app也是采用的grpc通信,之所以使用 grpc-message,也是需要向用户提示,如:密码错误,之类的业务提示。
- 同时我们后端还有异构语言,用 filter 添加 attach 的方式,显得过于复杂了。
@yl-yue 问题2:
- 框架内的异常,可能含有前置信息,不应该做为业务使用,当发生其他异常时均使用 unknown 抛出
- 中文乱码问题会在下个版本解决,如果想实现你的需求,使用 unknown 抛出即可
@yl-yue 提了个 pr 修复乱码问题,你可以尝试使用这个 pr 的代码测试一下
同样碰到乱码问题,provider抛出了异常,异常内容带有中文,consumer打印异常输出的中文是????