作者回复: 解释很清楚👍👍
作者回复: 太形象了👍👍👍
作者回复: 1. 分析正确,redis不太适合有的key的value特别大,这种情况会导致整个redis变慢,这种场景mc更好
2. prethread确实可以,mysql就是这种模式
3. 多reactor多线程再拆分业务线程,性能没有提升,复杂度提升不少,我还没见过这种方式。
作者回复: 分析正确
作者回复: 非常感谢,我明白了你说的情况,我再次验证了一下,写了一个独立线程处理业务的,确实如你所说,netty4两者都支持,并且做了线程安全处理,最终发送都是在io线程里面。
如果我们用这种模式,可以自己控制业务线程,因为netty4已经帮我们封装了复杂度,看来我孤陋寡闻了😂
不过我建议还是别无条件用这种模式,我们之前遇到的情况就是短时间内io确实很快,并发高,但如果业务处理慢,会积压请求数据,如果客户端请求是同步的,单个请求全流程时间不会减少;如果客户端请求是异步的,如果积压的时候宕机会丢较多数据。
其实这种情况我理解单纯加大线程数就够了,例如5个io线程加20个业务线程能达到最优性能的话,我理解25个融合线程性能也差不多。
我们之前有一个案例,http服务器业务处理线程配置了512个,后来发现其实配置128是最好的(48核),所以说并不是线程分开或者线程数量多性能就一定高。
再次感谢你的认真钻研,我也学到了一个技术细节👍
作者回复: 你两个问题的理解都正确
作者回复: 非常感谢你的认真研究和提问,我对netty的原理有一些研究,也用过netty3,也看过一些源码,但也还达不到非常熟悉的地步,所以不管是网上的资料,还是我说的内容,都不要无条件相信,自己都需要思考,这点你做的很好👍
回到问题本身,由于netty4线程模型和netty3相比做了改进,我拿netty4.1源码中的telnet样例,在handler和NioEventloop的processSelectedKey函数打了输出线程id的日志,从日志结果看,StringEncoder, StringDecoder, TelnetServerHandler都在NioEventLoop的线程里面处理的。
如果handler在独立的线程中运行,返回结果处理会比较麻烦,如果返回结果在业务线程中处理,会出现netty3存在的问题,channel需要做多线程同步,各种状态处理很麻烦;如果返回结果还是在io线程处理,那业务线程如何将结果发送给io线程也涉及线程间同步,所以最终其实还不如在一个线程里面处理。
作者回复: 分析正确👍
作者回复: 我理解这就是Reactor模式
作者回复: 两个轮询不是一个意思,select和poll是收到通知后轮询socket列表看看哪个socket可以读,普通的socket轮询是指重复调用read操作
作者回复: 功能是ok的,但复杂度不一样,参考架构设计的简单原则
作者回复: 1. 处理线程将返回结果包装成一个事件,触发write事件,详细可以看看Doug Lee的NIO PPT,处理线程和业务线程共享selector,key这些对象
2. io线程与业务线程分开就是单reactor多线程,多reactor如果再分开的话,性能没有提升,复杂度提升很多,我还没见过这种处理方式
作者回复: 连接你理解为tcp连接,请求你理解为一次sql语句执行
作者回复: 支持的,netty的NioDatagramChannel了解一下,直接用epoll也可以,epoll只管监听socket,tcp和udp都可以,差别在于udp只有一个socket描述符,因此只能用单Reactor