netty客户端引发的线程血案(二)
前言
前文讲解了基于netty-client 3.10.5如何出现的线程雪崩,线程雪崩时,可以观察到有规律的增加nio work线程和nio boss线程,在分析该问题的过程中,我们切换了es-client调用的netty库,尝试使用了netty的一些老的版本,发现在3.2.4版本上面不存在该问题,这又是什么原因导致的呢?本文我们分析一下3.10.5的机制。
Reactor
netty作为一个高性能的,异步非阻塞nio框架,采用的是Reactor模式,用来处理网络连接以及业务处理分发,典型的模型工作图见下:
基本工作原理,就是一个线程用来accept用户连接请求,然后将请求发送到处理器中,处理器采用多线程处理,提高处理效率。这是比较典型的netty服务端的处理,模式,在netty客户端基本沿用了这一模式,但是略微有些区别,本文主要用来分析netty客户端的实现,至于服务端,后续会逐步分析。
netty客户端
netty客户端在启动时,会启动2个线程次,一个boss线程池,一个work线程池,让我们看一下客户端启动时的设置,设置了2个线程池,一个bossExecutor,一个workerExecutor,按照默认大小启动,bossExecutor默认启动一个线程,workerExecutor启动Runtime.getRuntime().availableProcessors() * 2个线程,跟当前机器的核数有关,在我的四核机器上看是启动8个线程
public NioClientSocketChannelFactory(
Executor bossExecutor, Executor workerExecutor) {
this(bossExecutor, workerExecutor, DEFAULT_BOSS_COUNT, SelectorUtil.DEFAULT_IO_THREADS);
}
涉及到的几个关键类:
- NioClientSocketChannelFactory
- NioClientSocketPipelineSink
- NioWorkerPool
- NioWorker
- NioClientBossPool
- NioClientBoss
- NioSelector
在创建ClientBootstrap实例时,会创建并启动2个线程池,创建的数量见上文描述,bossExecutor通过NioServerBossPool->init->newBoss->NioClientBoss->AbstractNioSelector->openSelector
在openSelector中,会创建一个select,然后在线程池中启动一个线程,代码见下:
/**
* Start the {@link AbstractNioWorker} and return the {@link Selector} that will be used for
* the {@link AbstractNioChannel}'s when they get registered
*/
private