学习Dubbo-带你通过源码看看dubbo对netty的使用

1 public void connected(Channel channel) throws RemotingException {
2 ExecutorService executor = getExecutorService();
3 try {
4 executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.CONNECTED));
5 } catch (Throwable t) {
6 throw new ExecutionException(“connect event”, channel, getClass() + " error when process connected event .", t);
7 }
8 }

下面结合netty的调用流程对服务调用时的处理流程做一个梳理:netty的ServerBootstrap启动后,会开启bossGroup中的那个线程(即Reactor线程),一直执行run方法。而当有客户端要连接时,select方法会从操作系统获取到一个连接事件,Reactor线程会为该连接方创建一个NioSocketChannel,并从workerGroup中挑选一个线程,运行run方法,该线程用于处理服务端与这个客户端的后续通讯。而此处添加进pipeline中的nettyServerHandler会在客户端传来读写请求时触发对应的方法。最终调用到上述AllChannelHandler中的对应方法,用线程池执行后续业务逻辑。

二、Dubbo的客户端

1、客户端初始化

dubbo客户端初始化时会调用RegistryProtocol的refer方法,几经周折,最后到了DubboProtocol的protocolBindingRefer方法,如下,其中第5行调用的getClients方法是与netty整合的重点,即生成连接服务端的客户端。注意此处是在客户端中每一个引入的服务接口对应一个DubboInvoker。

1 public Invoker protocolBindingRefer(Class serviceType, URL url) throws RpcException {
2 optimizeSerialization(url);
3
4 // create rpc invoker.
5 DubboInvoker invoker = new DubboInvoker(serviceType, url, getClients(url), invokers); // 为每个invoker生成对应的nettyClient
6 invokers.add(invoker);
7
8 return invoker;
9 }

继续跟进,会进入NettyTransporter的connect方法,到这里应该会很熟悉,因为服务端初始化时调用的是该类下面的bind方法。bind方法初始化的是NettyServer对象,而connect初始化的是NettyClient对象。

public class NettyTransporter implements Transporter {

public static final String NAME = “netty”;

@Override
public RemotingServer bind(URL url, ChannelHandler listener) throws RemotingException {
return new NettyServer(url, listener);
}

@Override
public Client connect(URL url, ChannelHandler listener) throws RemotingException {
return new NettyClient(url, listener);
}

}

NettyClient的类图结构与NettyServer类似:

[图片上传失败…(image-881bf2-1614247162099)]

下面看NettyClient的构造器:

1 public NettyClient(final URL url, final ChannelHandler handler) throws RemotingException {
2 // you can customize name and type of client thread pool by THREAD_NAME_KEY and THREADPOOL_KEY in CommonConstants.
3 // the handler will be warped: MultiMessageHandler->HeartbeatHandler->handler
4 super(url, wrapChannelHandler(url, handler));
5 }

直接调用了父类构造器,其中wrapChannelHandler方法与NettyServer中的一样,不再赘述。下面看父类构造器:

1 public AbstractClient(URL url, ChannelHandler handler) throws RemotingException {
2 super(url, handler);
3
4 needReconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, false);
5 // 1、初始化客户端线程池
6 initExecutor(url);
7
8 try {
9 doOpen(); // 2、创建客户端的Bootstrap
10 } catch (Throwable t) {
11 // 省略异常处理
12 }
13 try {
14 // 3、连接Netty服务端
15 connect();
16 } catch (RemotingException t) {
17 // 省略异常处理
18 } catch (Throwable t) {
19 close();
20 // 抛异常
21 }
22 }

主要有三步,已经在上面标出,下面分别跟进这三个方法。

1)、initExecutor方法直接先将线程池类型添加进url中,客户端默认是Cached类型,所以在调用executorRepository.createExecutorIfAbsent(url)时会进入CachedThreadPool中。

1 private void initExecutor(URL url) {
2 url = ExecutorUtil.setThreadName(url, CLIENT_THREAD_POOL_NAME);
3 url = url.addParameterIfAbsent(THREADPOOL_KEY, DEFAULT_CLIENT_THREADPOOL);
4 executor &

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值