Netty的一些注意事项
- 一个EventLoopGroup当中会包含一个或多个EventLoop
- 一个EventLoop在他的整个生命周期中当中都只会与唯一一个Thread进行绑定
- 所有由EventLoop所处理的各种IO事件都将它所关联的那个Thread上进行处理
- 一个Channel在它的整个生命周期中只会注册在一个EventLoop上
- 一个EventLoop在运行过程当中,会被分配给一个或者多个Channel
重要结论:在Netty中,Channel的实现一定是线程安全的;基于此,我们可以存储一个Channel的引用,并且在需要向远程端点发送数据时,通过这个引用来调用Channel的相应的方法,即便在当时有很多线程在使用它也不会出现线程安全问题;而且消息一定会按照顺序发送出去。
重要结论:在业务开发过程中,不要将长时间执行的耗时任务放到EventLoop的执行队列中,因为他将会一直阻塞该线程所对应的所有Channel上的其他任务执行,如果我们需要进行阻塞调用或者耗时操作时(实际开发中很常见),那么我们就需要使用一个专门的EventExecutor(业务线程池)。
通常会有两种实现方式:
- 在ChannelHandler的回调方法中,使用自己的定义的业务线程池,这样可以实现异步调用
- 借助Netty提供的向ChannelPipline添加ChannelHandler时调用的addLast方法来传递EventExecutor。
说明:
默认情况下(调用addLast(Handler)),ChannelHandler中的方法都是用IO线程来执行的,如果调用了ChannelPipeline addFirst(EventExecutorGroup group, ChannelHandler... handlers);
方法,那么ChannelHandler中的回调方法就是用参数中的group线程组来执行的。
JDK所提供的Future只能通过手工的方式检查执行结果,而这个操作时会阻塞的;Netty则对ChannelFuture进行了增强,通过Channel
FutureListener以回调的方式来获取执行结果,出去了手工检查阻塞的操作;值得注意到是ChannelFutureListener的operationComplete方法是由IO线程执行的。因此不要在这里执行耗时操作,否则要用另外的线程或者线程池来执行。
网友评论