Skip to content

seata‐http2(grpc)‐protocol‐support

funkye edited this page Jul 1, 2024 · 3 revisions

协议设计

HTTP2

Header: id, compressor, messageType, headMap Body: 具体的Request/Response, 可以通过proto文件进行序列化/反序列化 使用http2的请求,固定使用protobuf进行序列化/反序列化。因此针对不同类型的消息, 序列化/反序列化需要用到proto文件, 这里可以复用seata-serializer-prtoobuf模块定义好的proto文件以及相关的PbConvertor image

HTTP

对于HTTP协议,只需要在服务端实现解析逻辑即可。使用Netty提供的HttpRequestDecoder和HttpObjectAggregator就可将ByteBuf转为FullHttpRequest,随后再根据请求路径和请求方法,将请求路由到对应的处理逻辑。 image

多协议适配

客户端

客户端可以在启动时就配置固定的协议类型 在NettyClientBootstrap的start方法中, 读取NettyClientConfig, 读取客户端选择的协议类型 (seata / grpc) 根据不同的协议类型, 配置不同的handler seata: ProtocolV1Decoder, ProtocolV1Encoder grpc: Http2FrameCodec, GprcDecoder, GprcEncoder image

服务端

服务端需要在运行时, 动态感知客户端请求的协议 在初始化时, 只配置一个MultiProtocolHandler MultiProtocolHandler会根据收到的消息, 选择不同的协议进行识别, 从而配置不同的handler image image

具体协议识别的示例代码如下

private final Map<String, SupportProtocol> protocols;
// ......
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out){
    Set<String> supportProtocolNames = new HashSet<>(protocols.keySet());
    for(String name: supportProtocolNames){
        SupportProtocol protocol = protocols.get(name);
        Result res = protocol.recognize(in);
        switch(res){
            case 未识别:
                continue;
            case 成功识别:
                // 获取该协议的handler
                ChannelHandler handler = handlerMap.get(name);
                ctx.pipeline().addLast(handler);
                ctx.pipeline().remove(this);
        }
    }
}

请求处理

HTTP2Decoder

当接收到HeaderFrame时, 会从Header中提取出id, compressor, messageType, headerMap, 作为RpcMessage的相应字段. 当接收到DataFrame时, 首先会调用decompress方法, 将data解压为字节数组, 随后, 调用Any.parseFrom将其解析为Any. Any中存有序列化时的类型信息(typeUrl), 可根据该类型信息, 将Any转化为对应的Java Proto对象. 最终使用PbConverter就可以将Java Proto对象转化为Request/Response类. HeaderFrame和DataFrame解析出的信息可以组成一个RpcMessage, 传递给后面的ServerHandler / ClinetHandler image

HTTP2Encoder

编码的过程是解码过程的逆序, 这里不再赘述 image

连接管理

channel管理

seata的channel管理是和请求的解析逻辑解耦的,具体是在请求解析之后的请求处理逻辑中(ServerHandler / ClientHandler)中进行的。本次改造不涉及对具体每个请求处理逻辑的改动,因此无需对现有的channel管理模型进行改动。

优雅关闭

seata目前在ServerHandler / ClientHandler的channelInavtive中已经有对于连接关闭情况的处理

Clone this wiki locally