公司 网站建设 会计科目,河北省建设项目环境官网网站,搜索引擎优化理解,景观设计论文分布式异步任务组件网络通信线程模型设计--
大概说一下功能场景#xff1a;
从节点和主节点建立连接#xff0c;负责和主节点的网络IO通信#xff0c;通信动作包括投票#xff0c;心跳#xff0c;举证等#xff0c;步骤为读取主节点的信息#xff0c;写入IO队列中
从节点和主节点建立连接负责和主节点的网络IO通信通信动作包括投票心跳举证等步骤为读取主节点的信息写入IO队列中然后从IO队列中读取解码翻译成具体的协议命令发送给上层线程处理或者从上层线程接受命令编码成字节流写入IO队列通信线程从IO队列中读取需要发送的字节buffer通过网络发送给主节点主节点和多个从节点建立连接负责每个从节点的网络IO通信包括投票心跳举证操作具体操作和从节点的操作相同多了一个建立连接的步骤--如图 初期线程模型设计--
每条网络数据传输通道一条线程即一条线程负责网络IO处理另外一条线程处理数据编解码整体使用同一个IOQueue--其实这里是两个读写队列分开但在线程模型里我们认为面对的是一个IOQueue即可如图
首先说一下线程拆分的原则--
基于事件反应器设计下的原子性保证--
NIO中的一个socketchannel面对的是一个连接底层可以理解为一个线程在处理数据IOIO事件通过selector发布这里一个selector可以处理多个Socket连接的多个事件但是selector本身的设计实现是同步模式的多线程读取selector中的事件需要阻塞也就是说同一时刻只能有一个线程读取selector中的事件并消费如果有多个线程同时监听selector中的事件未获取到锁的线程只能阻塞所以这里对一个selector对象只使用一个线程处理IO事件读写可以分开为两个事件
对于同一个通信连接中的数据可能出现拆包和粘包的现象所以这里对一个连接只使用一个IO队列相对应的对同一个读写队列也只使用一个线程来处理--但是这里读写队列是分开的
对于同一个命令的处理也应该是原子的所以对同一个命令也需要一个线程来操作
主要关注一下可以线程拆分的几个点
JavaNIO实现的TCP是半双工通道也就是同一个channel可以读也可写但是同一时刻只能进行读或者写操作中的同一个所以这点对于底层通信线程设计很重要同一个通信连接的读和写操作是否需要拆分 一个线程负责读数据一个线程负责写数据如果对一个Socketchannel的读写分开两个线程操作的话有两种设计方案一个socketchannel只注册到一个selector上读写线程各自监听同一个selector的读写事件分别处理读操作和写操作;另一种是两个线程分别拥有自己的selector每个线程从各自的selector上单独监听读事件或者写事件--这样其实已经违反了NIO设计的原则--NIO核心是一个线程可以监听多个channel如果一个channel使用多个线程监听的话反而不如使用BIO来处理因为channel实际上是半双工实现读和写操作都是同步进行的--综上读写同步进行的情况下使用多线程读写并不能实际上增加并发度因为如果读写分开的话读线程必须等写线程写完数据才可以读取反之一样而读写数据本身的操作只不过是完成一个队列操作另外如果多线程对同一IO队列并发读写要考虑顺序问题这里实现为为每个IO连接维护命令队列可以使用线程池进行编解码--具体那种效果最好要看后期压测结果