apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.39k stars 26.41k forks source link

Think of how Dubbo can better support http protocol. 设计支持 http 协议的编码与通信模式 #10805

Open chickenlj opened 1 year ago

chickenlj commented 1 year ago

Think of how Dubbo can better support HTTP protocol.

neighbor-uncleWang commented 1 year ago

i want to try.

frezea commented 1 year ago

i want to try

AlbumenJ commented 1 year ago
  1. 提供原生 Http 协议支持 目标:用户不需要引入 tomcat 或者 rest server 就可以发布 http 服务。 现状:待实现,需要从 transport 层(netty)往上写一个新的协议。底层最好兼容 H1、H2、H3,同时做到分层解耦,未来 triple 可以基于 H2 的底层统一实现。
kaori-seasons commented 1 year ago

@AlbumenJ 您好,经过一段时间的调研,发现dubbo3目前的rpc协议是在remoting通讯协议的基础之上实现的. 我理解您的意思是基于dubbo的dubbo-remoting-netty或者dubbo-remoting-netty4模块在上层进行封装新的rpc协议, 比如现在的dubbo-rpc-rest模块当中,http协议需要基于RestServer启动单独的线程,通过传入的http协议payload选择NettyServer和DubboHttpServer进行通信, 同时dubbo-rpc-rest模块依赖dubbo-remoting-http模块的缘故,使其需要基于tomcat或者Jetty这类servlet容器运行.对于上述所提到的从transport层往上写一个新的协议的这一问题, 调研的方案是基于现有的netty类remoting协议封装(dubbo-remoting-netty模块和dubbo-remoting-netty4模块)之上,重新封装成新的dubbo-rpc-http与dubbo-rpc-http2模块 对于http3, netty目前基于QUIC codec 编码器实现http3,根据情况可能需要适配一种新的父类型Codec

将来triple协议的封装也会在dubbo-rpc-http2的基础之上做改动. 不知道这样设计是否合理

AlbumenJ commented 1 year ago

基于现有的netty类remoting协议封装(dubbo-remoting-netty模块和dubbo-remoting-netty4)模块之上实现http和http2的codec

这个需要看 codec 是怎么实现的,直接依赖 netty 的还是自己实现一套。如果自己实现的话会比较复杂

kaori-seasons commented 1 year ago

基于现有的netty类remoting协议封装(dubbo-remoting-netty模块和dubbo-remoting-netty4)模块之上实现http和http2的codec

这个需要看 codec 是怎么实现的,直接依赖 netty 的还是自己实现一套。如果自己实现的话会比较复杂

@AlbumenJ ...可能是我没表达清楚,我的意思是指这样的重构方案是否合理.直接依赖 netty 的还是自己实现一套这个可以后面再做取舍. 只是我不确定这样子重构的架构是否符合社区的预期效果,即分别基于dubbo-remoting-netty模块和dubbo-remoting-netty4模块封装向上封装一层为dubbo-rpc-http与dubbo-rpc-http2模块. 废弃原来的dubbo-rpc-rest模块

kaori-seasons commented 1 year ago

已确认,基于门面模式为dubbo-remoting-netty与dubbo-remoting-netty4提供统一抽象,上层门面对接http1,http2,htp3,triple多协议

kaori-seasons commented 1 year ago

背景简介

在dubbo协议的设计当中,remoting-api是封装protocol的地方,rpc-api是将protocol暴露协议的地方

当地址出现变更的时候, dubbo的协议请求首先通过ServiceInstancesChangedListener#notifyAddressChanged 将地址变更通知registry-api, 通过registry-api将推送的地址更新到invoker的注册列表,然后在rpc-api当中进行协议转换(比如http协议即是通过RestProtocol编写http协议编码解码)

现在的问题点在于 原先RestProtocol#doExport中暴露地址的时候,需要新起一个RestProtocolServer线程来处理协议转换请求,通过选择对应的Binder(JettySerlvetBinder, TomcatSerlvetBinder, SerlvetHttpBinder) 获取serlvet上下文.在此过程当中分为两种实现DubboHttpProtocolServer和NettyRestProtocolServer。 其中NettyRestProtocolServer是不支持在serlvet容器注入对象的时候使用(即Binder为tomcat, jetty类型时). 同时耦合比较严重,不是基于Transporter层(dubbo-remoting-netty和dubbo-remoting-netty模块的通信层)封装,不好维护

以其中一个协议为例子进行改造

 DemoService service = new DemoServiceImpl();
        int port = NetUtils.getAvailablePort();
        protocol.export(proxy.getInvoker(service, DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange")));
        service = proxy.getProxy(protocol.refer(DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + DemoService.class.getName() + "?codec=exchange").addParameter("timeout",
            3000L)));
        assertEquals(service.getSize(new String[]{"", "", ""}), 3);

在dubbo的provider侧 在暴露协议之前,也就是在封装protocol的时候实现相关协议的codec, 然后在AbstractProtcol协议进行refer转发到代理的时候,将从url中收集到的invoker列表以及codec信息传入Protocol接口下的实现Http1Protocol和Http2Protocol 调用NettyTransporter#bind对传下来的invoker地址(refer方法)进行监听.

在dubbo的consumer侧 由于consumer调用provider请求会在AbstractProxyFactory#export层对上层provider传递下来的地址进行地址暴露,在此调用NettyTransporter.connect 消费相关的Url信息,交给对应protocol#export进行解码处理

综上所述,其实就相当于以前的RestProtocolServer换成了NettyTransporter#bind底层调用的NettyServer 在protocol当中实现http1/http2的编码协议