32 网友分享了链接
2020-08-22 06:24:47
Netty 通过 Reactor 模型基于多路复用器接收并处理用户请求,内部实现了两个线程池, boss 线程池和 work 线程池,其中 boss 线程池的线程负责处理请求的 accept 事件,当接收 到 accept 事件的请求时,把对应的 socket 封装到一个 NioSocketChannel 中,并交给 work 线程池,其中 work 线程池负责请求的 read 和 write 事件,由对应的 Handler 处理。 单线程模型:所有 I/O 操作都由一个线程完成,即多路复用、事件分发和处理都是在一个 Reactor 线程上完成的。既要接收客户端的连接请求,向服务端发起连接,又要发送/读取请 求或应答/响应消息。一个 NIO 线程同时处理成百上千的链路,性能上无法支撑,速度 慢,若线程进入死循环,整个程序不可用,对于高负载、大并发的应用场景不合适。 多线程模型:有一个 NIO 线程(Acceptor) 只负责监听服务端,接收客户端的 TCP 连接 请求;NIO 线程池负责网络 IO 的操作,即消息的读取、解码、编码和发送;1 个 NIO 线 程可以同时处理 N 条链路,但是 1 个链路只对应 1 个 NIO 线程,这是为了防止发生并发 操作问题。但在并发百万客户端连接或需要安全认证时,一个 Acceptor 线程可能会存在性 能不足问题。 主从多线程模型:Acceptor 线程用于绑定监听端口,接收客户端连接,将 SocketChannel 从主线程池的 Reactor 线程的多路复用器上移除,重新注册到 Sub 线程池的线程上,用于 处理 I/O 的读写等操作,从而保证 mainReactor 只负责接入认证、握手等操作; 5.TCP 粘包/拆包的原因及解决方法? TCP 是以流的方式来处理数据,一个完整的包可能会被 TCP 拆分成多个包进行发送,也可 能把小的封装成一个大的数据包发送。 TCP 粘包/分包的原因: 应用程序写入的字节大小大于套接字发送缓冲区的大小,会发生拆包现象,而应用程序写 入数据小于套接字缓冲区大小,网卡将应用多次写入的数据发送到网络上,这将会发生粘 包现象; 进行 MSS 大小的 TCP 分段,当 TCP 报文长度-TCP 头部长度>MSS 的时候将发生拆包 以太网帧的 payload(净荷)大于 MTU(1500 字节)进行 ip 分片。 解决方法 消息定长:FixedLengthFrameDecoder 类 包尾增加特殊字符分割:行分隔符类:LineBasedFrameDecoder 或自定义分隔符类 : DelimiterBasedFrameDecoder 将消息分为消息头和消息体:LengthFieldBasedFrameDecoder 类。分为有头部的拆包与粘 包、长度字段在前且有头部的拆包与粘包、多扩展头部的拆包与粘包。