根据我们前面分析的,接收到消息后,为了避免在I/O线程里执行耗时的操作,一般都会使用线程池来执行业务处理逻辑.
那是使用Netty提供给我们的方法,传入一个线程池还是使用我们自己定义的线程池好呢?
先来看Netty给我们提供的
ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler);
即我们添加handler的时候可以传入一个线程池进去
DefaultEventExecutorGroup
它与NioEventLoop之间的区别又是什么?
NioEventLoop
侧重于处理网络I/O相关的各种事件,例如连接操作,消息读取和发送操作
DefaultEventExecutor
侧重于处理业务相关的逻辑,将业务的ChannelHandler与具体的DefaultEventExecutor绑定起来.
EventLoop继承图.png
其次
对于某个客户端连接Channel,只会注册到一个NioEventLoop线程中,用于处理网络I/O操作,业务的ChannelHandler指定了运行线程池EventLoopGroup之后,创建ChannelHandlerContext上下文时会从EventLoopGroup中选择一个EventExecutor绑定到该Channel对应的ChannelHandler实例.
也就是说使用netty提供默认的,是绑定的.如下图
业务绑定EventExecutor模型的线程模型.png
使用我们自己定义的线程池
业务自定义线程池模型的线程模型.png
虽然LinkedBlockQueue通过读写锁来提升性能,但是当业务线程数和写操作比较多时,锁竞争对性能的影响还是比较大的。
如果采用自定义线程池时,优化方向就是锁消除.
可以使用Disruptor或者使用ChannelId与业务线程池中的某个业务进行绑定