dubbo源码深度解读四之remoting模块

来源:互联网 发布:通达信原油看盘软件 编辑:程序博客网 时间:2024/06/06 08:44

前言:remoting模块是远程通讯模块,相当于Dubbo协议的实现,是一个为Dubbo项目处理底层网络通信的层。具体结合了netty,mina等进行实现。

一,dubbo-remoting-api
首先结合文档的图先了解一下基础接口包的主要类。
这里写图片描述
1,ChannelHandler是抽象的通道事件处理器,同时注意到它的注解也是SPI

@SPIpublic interface ChannelHandler {    void connected(Channel channel) throws RemotingException;    void disconnected(Channel channel) throws RemotingException;    void sent(Channel channel, Object message) throws RemotingException;    void received(Channel channel, Object message) throws RemotingException;    void caught(Channel channel, Throwable exception) throws RemotingException;}

2,Codec2.接口定义了编码解码规范,与废弃的接口Codec相比,Codec2没有依赖jdk的输入输出流, 以dubbo的ChannelBuffer为核心便于更好的整合(关于各个Codec2的实现类例如DubboCodec,会和rpc模块一起深入解读)

@SPIpublic interface Codec2 {    @Adaptive({Constants.CODEC_KEY})    void encode(Channel channel, ChannelBuffer buffer, Object message) throws IOException;    @Adaptive({Constants.CODEC_KEY})    Object decode(Channel channel, ChannelBuffer buffer) throws IOException;    enum DecodeResult {        NEED_MORE_INPUT, SKIP_SOME_INPUT    }}

3,Transporter
bind 根据URL和ChannelHandler 生成Server, connect 根据URL和ChannelHandler

@SPI("netty")public interface Transporter {    @Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})    Server bind(URL url, ChannelHandler handler) throws RemotingException;    @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})    Client connect(URL url, ChannelHandler handler) throws RemotingException;}

4,Endpoint。Client和Server都继承的一个接口类

5,Dispatcher。定义channelHandler对Channel的操作(哪些走线程池)

@SPI(AllDispatcher.NAME)  public interface Dispatcher {      @Adaptive({Constants.DISPATCHER_KEY, "dispather", "channel.handler"}) // 后两个参数为兼容旧配置      ChannelHandler dispatch(ChannelHandler handler, URL url);  }  

二,服务端集成netty
1,先看下NettyServer的类图
这里写图片描述

2,处理流程
这里写图片描述
其中Netty区域的类,都是扩展了了Netty自带类。
1.1 InternalDecoder:负责TCP层协议的解析,处理TCP粘包。(当然这个解析也包含序列化的处理)。
1.2 InternalEncoder: 协议封装。
1.3 NettyHandler:客户通道共享的处理器(请参阅Netty的通道处理器模型),转换Netty的通道事件到Dubbo事件。
1.4 NettyServer:处理连接数量。
1.5 MultiMessageHandler:多消息处理。
1.6 HeartbeatHandler:心跳消息。
1.7 AllChannelHandler:委派业务请求到线程池。

3,NettyHandler的实现
继承org.jboss.netty.channel.SimpleChannelHandler,来处理org.jboss.netty.channel.Channel的连接读写事件。此时NettyHandler就可以委托dubbo的com.alibaba.dubbo.remoting.ChannelHandler接口实现来完成具体的功能,在交给com.alibaba.dubbo.remoting.ChannelHandler接口实现之前,需要先将netty自己的org.jboss.netty.channel.Channel channel转化成上述的NettyChannel。
其实就是相当于转换Netty的通道事件到Dubbo事件
摘取部分代码来看一下就知道了

@Override    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {        NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(), url, handler);        try {            if (channel != null) {                channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.getChannel().getRemoteAddress()), channel);            }            //转换到ChannelHandler的connected            handler.connected(channel);        } finally {            NettyChannel.removeChannelIfDisconnected(ctx.getChannel());        }    }

4,NettyServer启动流程
这里写图片描述
按照netty自己的API启动方式,然后依据外界传递进来的com.alibaba.dubbo.remoting.ChannelHandler接口实现,创建出NettyHandler,最终对用户的连接请求的处理全部交给NettyHandler来处理,NettyHandler又交给了外界传递进来的com.alibaba.dubbo.remoting.ChannelHandler接口实现。
至此就将所有底层不同的通信实现全部转化到了外界传递进来的com.alibaba.dubbo.remoting.ChannelHandler接口的实现上了。

而上述Server接口的另一个分支实现HeaderExchangeServer则充当一个装饰器的角色,为所有的Server实现增添了如下功能:
向该Server所有的Channel依次进行心跳检测:

  • 如果当前时间减去最后的读取时间大于heartbeat时间或者当前时间减去最后的写时间大于heartbeat时间,则向该Channel发送一次心跳检测
  • 如果当前时间减去最后的读取时间大于heartbeatTimeout,则服务器端要关闭该Channel,如果是客户端的话则进行重新连接(客户端也会使用这个心跳检测任务)

三,客户端集成Netty
服务器端了解了之后,客户端就也非常清楚了,整体类图如下:
这里写图片描述
NettyClient在使用netty的API开启客户端之后,仍然使用NettyHandler来处理。还是最终转化成com.alibaba.dubbo.remoting.ChannelHandler接口实现上了。
我们可以看到这样集成完成之后,就完全屏蔽了底层通信细节,将逻辑全部交给了com.alibaba.dubbo.remoting.ChannelHandler接口的实现上了。从上面我们也可以看到,该接口实现也会经过层层装饰类的包装,才会最终交给底层通信。

原创粉丝点击