1. 前置准备
Selector 的 wakeup 操作
官方文档的不准确翻译 .
- Causes the first selection operation that has not yet returned to return immediately. 解除阻塞在Selector.select()/select(long)上的线程,立即返回
- 如果在调用select()或select(long)方法的过程中,当前有另一个线程被阻塞,那么该调用将立即返回。
- 当前没有选择操作正在进行,那么这些方法中的一个方法的下一次调用将立即返回,除非在此期间调用了selectNow()方法。
- 在任何情况下,该调用返回的值可能是非零。随后对select()或select(long)方法的调用将像往常一样阻塞,除非在此期间再次调用该方法。
在两个连续的选择操作之间调用本方法一次以上与只调用一次的效果相同。
Linux 上的实现原理是 利用 pipe 系统调用实现了一个管道. wakeup 会在管道中写入一个 Byte , 这样就产生了事件、 立即返回. 从实现上来看, 是有不可忽视的性能开销 ;
2. 接收源码分析
2.1 概述
-
- 记得之前 初始化 ServerSocketChannel 的时候, pipeline 中增加了
ServerBootstrapAcceptor . 这是 ServerSocketChannel 唯一的 Handler .
- 对于
ServerBootstrapAcceptor, 接受连接就是 channelRead 一下而已, 此时处理的线程是 boss 线程
- 收到的 msg 自然是 accept 到的 SocketChannel 这个子连接了
-
- 然后 workerEventLoopGroup 去 reg 一下这个 msg 就结束了 .
- 有点明了了, reg 的意思就是 把 EventLoop 和 channel 绑定起来 .
- chooser 的 next 只是选择 eventLoop、 不需要等待
- boss 线程中 绑定 work Loop 肯定要发生线程切换 .
- 一个 EventLoop 对应一个 Thread 线程资源, 多个线程并发安全的添加任务、当然是 MpSc 的场景了
- 跟之前一样, reg 会创建 SelectKey , 但是不对 Read 感兴趣
-
- reg 之后一堆 和 之前 ServerSocketChannel 一样又到了 对 read 感兴趣
- 和 ServerSocketChannel 一毛一样, 为啥? 因为对于 ServerSocketChannel 是 read 事件、 对于 SocketChannel 有数据也是 read 事件、是一毛一样的 ~