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 &