Dubbo——各协议暴露和引用服务的逻辑

来源:互联网 发布:苹果5s蜂窝数据打不开 编辑:程序博客网 时间:2024/06/05 09:59

各协议暴露和引用服务的逻辑

目前Dubbox版本支持的协议有dubboinjvmrmihessianthriftmemcachedredisrest等九种,其中memcachedredis协议只支持服务引用不支持服务暴露;这些协议有的继承AbstractProxyProtocol类,有的实现了AbstractProtocol接口。服务暴露调用export方法,引用服务调用refer方法。

1、各协议暴露服务逻辑

服务暴露之后会创建Exporter 对象,并将此对象存入AbstractProtocol.exporterMap:Map<String, Exporter<?>>中。其中key的组成方式:serviceGroup/serviceName:serviceVersion:port,serviceName是配置protocol的contextpath属性值+ dubbo:service的interface值,serviceGroup 为group属性值,serviceVersion为version属性值,若该属性值为空或者为“0.0.0”则在key中忽略此部分。从而可以看出在同一个协议下面是否为同一服务由上述属性决定。

1.1 Duboo协议

1)初始化DubboExporter对象,初始化参数包括invoker对象,key,以及AbstractProtocol.exporterMap引用,并存入AbstractProtocol.exporterMap中;消费端发起的远程调用通过底层消息通道的传输到服务端之后,此类中根据服务端URL生成的key在AbstractProtocol.exporterMap中查找到相应的Exporter对象,通过此Exporter对象找到Invoker对象,调用Invoker.invoke()方法,继续向上传递至服务端的业务层,进行业务逻辑的调用。

2)开启服务,如下代码所示,对于相同的服务提供者IP和端口号,只开启一个服务监听通道,该通道封装在ExchangeServer对象中。若相同的服务提供者再次开启服务,则只调用ExchangeServer对象的reset方法进行服务通道的重新设置,例如监听线程池大小、心跳频率等参数的重新设置。


3)创建ExchangeServer对象。具体过程如下:

3.1)检查<dubbo:protocol>标签的server属性配置值是否支持,目前Dubbo协议服务端支持的NIO框架有netty、mina、grizzly三种,缺省为netty;

3.2)在DubboProtocol类中实例化内部类得到ExchangeHandler对象,该内部类继承了ExchangeHandlerAdapter 类,并实现了reply、received、connected、disconnected四个方法。

3.3)调用Exchangers.bind(URL url, ExchangeHandlerhandler)方法创建ExchangeServer对象,其中入参url为服务端提供服务的URL,handler为内部匿名类DubboProtocol $requestHandler。

3.4)根据URL地址的exchanger参数获取具体的Exchanger类,目前只支持HeaderExchanger。则调用HeaderExchanger. bind(URL url, ExchangeHandlerhandler)方法,在此方法中创建HeaderExchangeServer对象。具体过程如下:

3.4.1)用HeaderExchangeHandler类封装上述内部匿名类;该类的主要作用有两个:第一,对通道的读写时间戳进行更新,用于辅助心跳检测;第二,发起回调客户端的服务;

               3.4.2)用DecodeHandler类对上面的类进行封装,该类是对信息进行序列化以及反序列化操作,对有回调函数的远程消费要生成回调函数的代理作为参数传递到上层;

               3.4.3)然后调用Transporters.bind(URL url, ChannelHandler...handlers)方法生成Server对象。若入参有多个handlers对象,则使用ChannelHandlerDispatcher类进行封装;根据<dubbo:protocol>标签的server属性配置的NIO框架来选择调用具体的Transporter类的bind方法,对于mina框架创建MinaServer对象,netty框架创建NettyServer对象,grizzly框架创建GrizzlyServer对象,返回具体的Server对象。在初始化Server对象的过程中,第一,完成服务端口的启动并监听消息通道;第二,调用ChannelHandlers.wap(ChannelHander,URL)方法将上面的DecodeHandler对象依次通过AllChannelHandler、HeartbeatHandler、MultiMessageHandler的进行封装,最后赋值给Server对象的ChannelHandler成员变量。

              3.4.4)最后调用HeaderExchangeServer(Server server)方法,用HeaderExchangeServer类封装上面的Server对象,该类主要是启一个线程来定时发送链路的心跳。

     下图为各个类的封装结构图


         下图为Dubbo协议暴露服务的处理逻辑活动图


1.2 Rest协议

1、检查AbstractProtocol.exporterMap中是否存在该URL的Server对象,若没有则调用RestServerFactory.createServer(String name)方法创建,参数name由URL中的参数server的值指定,目前支持如下参数值。

       1)值为“servlet”、“jetty”、“tomcat”时创建DubboHttpServer对象;

       2)值为“netty”时创建NettyServer对象,内部封装了NettyJaxrsServer对象;

       3)值为“sunhttp”时创建SunHttpServer对象,内部封装了SunHttpJaxrsServer对象;

2、如果server 参数的值等于“servlet”则从ServletManager.contextMap中获取key=-1234 的ServletContext对象;并且必须配置外部servlet对象的上下文路径与URL的上下文路径contextpath一致。

ServletManager类维护全局唯一的Map,保存全局的上下文对象,key=-1234的ServletContext对象是在BootstrapListener的contextInitialized 方法中被存入进去的,该类实现了ServletContextListener接口,在外部servlet服务启动时将该服务的上下文加入到此全局Map中。因此需要在web.xml中配置BootstrapListener。

3、在上下文路径下面发布Expoter对象;代码如下:


2各协议引用服务逻辑

2.1 Duboo协议

1、创建ExchangeClient对象。若服务提供者URL地址中有connections参数值(在<dubbo:service >标签中配置),则每个服务创建指定条数的链路(即ExchangeClient对象);若没有参数则服务消费端与服务提供端直接的所有服务共用一条长链接(即ExchangeClient对象)。

1)获取服务端配置的client参数,若缺省则使用server参数配置,默认选择netty;

2)设置心跳heartbeat=60000

3)为了减小长连接数,可以设置是否延迟链接,配置<dubbo:protocol>的参数lazy;当lazy=true时,则创建LazyConnectExchangeClient对象,待真正发起远程调用时,再创建ExchangeClient对象(即与服务端创建连接);否则立刻调用HeaderExchanger.connect方法创建与服务端的链接(HeaderExchangeClient对象),具体过程如下:

3.1)在DubboProtocol中创建了内部匿名类DubboProtocol $requestHandler,该类实现了抽象类ExchangeHandlerAdapter。

3.2)用HeaderExchangeHandler类封装上述内部匿名类;该类的主要作用有两个:第一,对通道的读写时间戳进行更新,用于辅助心跳检测;第二,发起回调客户端的服务。

3.3)用DecodeHandler类对上面的类进行封装,该类是对信息进行序列化以及反序列化操作,对有回调函数的远程消费要生成回调函数的代理作为参数传递到上层;

3.4)调用Transporters. connect (URL url,ChannelHandler... handlers)方法创建Client对象。若入参有多个handlers对象,则使用ChannelHandlerDispatcher类进行封装;根据<dubbo:protocol>标签的client属性配置的NIO框架来选择调用具体的Transporter类的connect方法,对于mina框架创建MinaClient对象,netty框架创建NettyClient对象,grizzly框架创建GrizzlyClient对象,返回具体的Client对象。在初始化Client对象的过程中,第一,完成与服务端的建链;第二调用ChannelHandlers.wap(ChannelHander,URL)方法将上面的DecodeHandler对象依次通过AllChannelHandler、HeartbeatHandler、MultiMessageHandler的进行封装,最后赋值给Client对象的ChannelHandler成员变量。

3.5)最后调用将上述client对象通过HeaderExchangeClient构造函数封装成HeaderExchangeClient对象并返回。

4)用ReferenceCountExchangeClient封装上面的HeaderExchangeClient对象;

2、初始化DubboInvoker对象,并返回该对象。

 

下图是类之间封装的结构图


下图为Dubbo协议引用服务的活动图


2.2 Rest协议

1、采用RestEasy技术创建与服务消费端的链接;

2、通过代理工厂ProxyFactory$Adpative创建上面链接对象的代理对象Invoker;

3、实现内部类并返回该内部类的初始化对象,该内部类继承AbstractInvoker类,并重现了doInvoke方法,在该方法中调用上面Invoker对象的invoke方法。





原创粉丝点击