sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.53k stars 1.12k forks source link

gRPC 场景下如何处理服务端的异常消息 #1063

Closed googlefan closed 6 months ago

googlefan commented 6 months ago

Your question

@fengjiachun 大佬 问个问题:

Describe your question clearly 我在 使用gRPC impl 作为raft rpc 的实现,在定义 请求-返回 映射map时,我有个疑问, 如果一个请求 有不同的返回消息实体,怎么办? 或者如果一个请求,当服务端发生了业务异常,想 将业务异常 消息抛给 客户端,怎么办? 在 构造MarshallerHelper 这个对象时,由于它是Map 类型的数据结构,key - value 是多对一的, 而不是一对多的,那么一个request 就只有一个固定的response 了: ` public static void initGRpc() { if ("com.alipay.sofa.jraft.rpc.impl.GrpcRaftRpcFactory".equals(RpcFactoryHelper.rpcFactory().getClass() .getName())) { RpcFactoryHelper.rpcFactory().registerProtobufSerializer(CounterOutter.GetValueRequest.class.getName(), CounterOutter.GetValueRequest.getDefaultInstance()); RpcFactoryHelper.rpcFactory().registerProtobufSerializer( CounterOutter.IncrementAndGetRequest.class.getName(), CounterOutter.IncrementAndGetRequest.getDefaultInstance()); RpcFactoryHelper.rpcFactory().registerProtobufSerializer(CounterOutter.ValueResponse.class.getName(), CounterOutter.ValueResponse.getDefaultInstance());

        try {
            Class<?> clazz = Class.forName("com.alipay.sofa.jraft.rpc.impl.MarshallerHelper");
            Method registerRespInstance = clazz.getMethod("registerRespInstance", String.class, Message.class);
            registerRespInstance.invoke(null, CounterOutter.GetValueRequest.class.getName(),
                CounterOutter.ValueResponse.getDefaultInstance());
            registerRespInstance.invoke(null, CounterOutter.IncrementAndGetRequest.class.getName(),
                CounterOutter.ValueResponse.getDefaultInstance());
        } catch (Exception e) {
            LOG.error("Failed to init grpc server", e);
        }
    }
}

` 如上代码,假如 CounterOutter.IncrementAndGetRequest 这个请求在 服务端throw 了 bunisessException, 此时 由于已经定义了 CounterOutter.ValueResponse.getDefaultInstance() 消息 实例, bunisessException 消息就无法返回给客户端了吧

Your scenes

我想将异常抛给客户端(gRPC) Describe your use scenes (why need this feature)

Your advice

Describe the advice or solution you'd like

Environment

fengjiachun commented 6 months ago

你好,别喊大佬啊我不是... 对于你的问题,业务异常信息放到 ValueResponse 的 errorMsg 不行吗?

googlefan commented 6 months ago

你好,别喊大佬啊我不是... 对于你的问题,业务异常信息放到 ValueResponse 的 errorMsg 不行吗?

哈哈,不要谦虚. 你说的方案操作是 可行的,但是很不方便, 像 bolt rpc 是可以基于返回的消息 做instanceof 类型判断 的, 而 grpc 就定死了 了一个请求一个返回. 我在接口设计时, 想做一些动态的消息返回 也没法做. 而且 请求的返回 消息全部包含 异常的消息, 从设计上就没隔离开,很不优雅

fengjiachun commented 6 months ago

嗯,我没有其他办法,这个问题与 jraft 关系不大,这里就不深入讨论了 ,暂时先关闭这个 issue 了