当前位置: 首页 > 后端技术 > Java

Dubbo服务器服务导出(暴露)流程研究

时间:2023-04-02 00:06:29 Java

本文主要讲dubbo的服务导出部分,即服务暴露。服务导出的核心接口是Protocol的导出方法;暴露方式有很多种(tcp/http/rmi/webservice等),也可以同时暴露多种方式,dubbo基于接口SPI的扩展非常灵活,完全依赖于实现协议本身;服务器接口的声明和实现如下:来自提供者:“+RpcContext.getContext().getLocalAddress();}}publicclassProvider{privatestaticvoidmain(String[]args){DemoServicedemoService=newDemoServiceImpl();ApplicationConfigapplication=newApplicationConfig();application.setName("演示");RegistryConfigregistry=newRegistryConfig();registry.setAddress("127.0.0.1:2181");registry.setProtocol("动物园管理员");协议=新协议配置();protocol.setName("dubbo");protocol.setPort(20880);protocol.setServer("netty4");ServiceConfigservice=newServiceConfig();服务.setApplication(应用程序);service.setRegistry(注册表);服务.setProtocol(协议);service.setInterface(DemoService.class);service.setRef(演示服务);服务.出口();系统.in.read();}}由于dubbo最近版本变化比较大,但是其核心接口没有变化,所以这里以2.6.x版本为例。由于我们选择的服务端实现是netty4,所以我们在netty的AbstractBootstrap.bind方法上加了一个断点,得到的调用栈如下:25.bind:264,AbstractBootstrap(io.netty.bootstrap)24。doOpen:119,NettyServer(com.alibaba.dubbo.remoting.transport.netty4)23。:88,AbstractServer(com.alibaba.dubbo.remoting.transport)22.:81,NettyServer(com.alibaba.dubbo.remoting.transport.netty4)21.bind:33,NettyTransporter(com.alibaba.dubbo.remoting.transport.netty4)20.bind:-1,Transporter$Adaptive(com.alibaba.dubbo.远程处理)19。bind:60,转运器(com.alibaba.dubbo.remoting)18。bind:46,HeaderExchanger(com.alibaba.dubbo.remoting.exchange.support.header)17.bind:72,交换器(com.alibaba.dubbo.remoting.exchange)16。createServer:430,DubboProtocol(com.alibaba.dubbo.rpc.protocol.dubbo)15.openServer:393,DubboProtocol(com.alibaba.dubbo.rpc.protocol.dubbo)14.export:371,DubboProtocol(com.alibaba.dubbo.rpc.protocol.dubbo)13.export:123,ProtocolFilterWrapper(com.alibaba.dubbo.rpc.protocol)12.export:59,ProtocolListenerWrapper(com.alibaba.dubbo.rpc.protocol)11.export:-1,Protocol$Adaptive(com.alibaba.dubbo.rpc)10。doLocalExport:172,RegistryProtocol(com.alibaba.dubbo.registry.integration)9.4-doRegister:140,ZookeeperRegistry(com.alibaba.dubbo.registry.zookeeper)9.3-register:150,FailbackRegistry(com.alibaba.dubbo.registry.支持)9.2-register:129,RegistryProtocol(com.alibaba.dubbo.registry.integration)9.出口:135,RegistryP协议(com.alibaba.dubbo.registry.integration)8.export:120,ProtocolFilterWrapper(com.alibaba.dubbo.rpc.protocol)7.export:56,ProtocolListenerWrapper(com.alibaba.dubbo.rpc.protocol)6.export:-1,Protocol$Adaptive(com.alibaba.dubbo.rpc)5.doExportUrlsFor1Protocol:514,ServiceConfig(com.alibaba.dubbo.config)4.doExportUrls:359,ServiceConfig(com.alibaba.dubbo.config)3.doExport:318,ServiceConfig(com.alibaba.dubbo.config)2.export:216,ServiceConfig(com.alibaba.dubbo.config)1。main:,Provider(com.alibaba.dubbo.demo.provider)服务暴露主要分为两步,一是本地服务暴露,二是服务注册。上面的调用栈主要体现了局部暴露。支线9.2是服务注册逻辑。下面从栈底往上拆解:1.入口函数mainFunction2-3,ServiceConfig是服务配置类,负责配置解析、验证、组装、服务暴露的调用入口,防止重复导出等。协议被暴露和导出。这里有很多代码是把url和它的参数组装起来,然后exportinjvm,再exportProtocolProtocol。这里可能看起来有点迷惑,为什么你用protocol.export导出了,导出的结果却不一样。这就是SPI的自适应能力。具体书是protocol.export会根据传入参数的url寻找合适的实现类。出口;在本地导出的时候把url的protocol设置为injvm,在导出registry的时候把protocol设置为registry,然后找到各自的实现类进行导出。这里涉及到SPI的自适应@Adaptive注解的实现,就不多说了;6.Protocol$Adaptive是SPI适配的实现。它是通过代码生成实现的,所以这里看不到源码。7、ProtocolListenerWrapper是Protocol的一个增强的SPIWrapper类,会自动装饰在Protocol的实现类中,这仍然是SPI的功能;这里因为registry的导出逻辑会直接跳过filter链的组装逻辑,可以查看ProtocolListenerWrapper.export方法8.ProtocolFilterWrapper也是Protocol的一个增强的SPIWrapper类,主要作用是创建一个filter链。如果你看过客户端调用的文章,这里也出现了这个类。总的来说就是为server和client建立一个filterchain;这里,因为是registry导出逻辑,所以会直接跳过filter链的组装逻辑,详见ProtocolFilterWrapper.export方法。9、RegistryProtocol是注册中心导出的核心类,内部封装了注册服务的通用逻辑,通过相应的注册中心接口适配不同的注册中心;9.2-9.4是注册服务的逻辑;10、RegistryProtocol.doLocalExport方法有点眼熟。ServiceConfig中还有一个exportLocal方法,是用来导出injvmProtocol的,不过RegistryProtocol.doLocalExport的作用是在这里导出真正的应用协议是DubboProtocol11-13,是大家熟悉的一套SPI自适应导出协议。这里url的协议已经是dubbo了。ProtocolListenerWrapper和ProtocolFilterWrapper分别增强加入监听和过滤链。这里会进行构建过滤器链的逻辑14,进行DubboProtocol的导出逻辑,结合Invoker和filter链表的头部被打包到一个导出器中进行缓存。当真正的业务网络请求到来时,可以在缓存中找到真正的Invoker链并调用。15、DubboProtocol.openServer开始暴露网络接口,即网络监控。由于端口只能被监听一次,如果一个端口上暴露了多个接口。这里会进行端口复用,也就是监听完成后,缓存起来。下次会判断host:port是否已经被缓存用于监控。如果它已被监控,它将被重复使用。16.DubboProtocol.createServer创建服务端监听逻辑,最后调用Exchangers.bind开启一个网口;值得一提的是,在DubboProtocol中创建了一个ExchangeHandlerAdapter类型的requestHandler来处理网络请求。它的主要作用是在exporter缓存中找到对应的Invoker调用网络请求参数然后Return;17-18。Exchangers是Exchanger的工厂类。通过SPI找到Exchanger的实现类HeaderExchanger来实现。19-21。Transporters是Transporter的工厂类。通过SPI找到Transporter的实现类NettyTransporter,对端口进行监听。同学们可能已经发现这里有个Transporter$Adaptive.bind,而Exchanger没有。这是因为他们在获取实现类时使用了不同的调用方式。个人觉得操作应该用Adaptive类,不然可能Exchanger用处不大。扩展的可能性不大,默认只有一个实现类,但是Transporter的实现类很多,扩展的可能性也很大22-25。调用最终的nettyServer实现监听端口;