nio的成本和收益以及客户端是否需要使用nio
nio额外成本: 需要额外安排一个网络线程池
是否需要使用nio? 分节省线程和节省连接两个角度讨论下:
一. 是否节省线程:
服务端: 肯定是要的, 收益: 通过多路复用, 增加安排少量的网络线程即可监听成千上万的端口(客户端连接事件), 而不用阻塞服务端的大量业务线程
客户端: 看情况:
1.场景一, 没节省. 安排了网络线程池, 却没有受益, 或者是负受益, 如果本身就是同步场景, 业务线程必须要等待http结果才能处理下一步, 并且不能放在网络线程回调中处理(网络线程不能处理太慢的业务, 就像netty一样), 这种情况还是挺多的.
2.场景二, 节省了, 业务线程直接不鸟这个结果了, 不满足场景一的, 比如, 调用方业务不用同步等结果, 可以在网络线程的响应回调中执行 (大不了多开点网络线程), 或者就只要调一个就行了, 对于响应的处理并不复杂耗时
二. 是否节省连接
这个只讨论客户端就行了, 因为连接客户端发起的.
节省连接实际就是看能否并发请求, 并发请求的前提是client有办法把请求和响应对应起来, 也就是要看使用的协议. 比如dubbo.
http1.1 : 是不行的
http2 :
a. 天生多请求复用一个tcp连接 (省了连接池), 并发请求, 如果通信双方实现了http2.
b. 建议使用HttpAsyncClient (一般来说, 都会双方会智能协商http使用版本, 优先使用高版本. 协商成了就赚了, 降级成低版本也就比bio多损耗一点点, 长期来看应该是收益大的)
c. 上文提到, 并发请求的前提是client有办法把请求和响应对应起来这是要有线程去干这个活的, 很显然, 这个活得网络线程干. 所以选择http2还是得用nio, 就好比duboo的客户端使用了netty nio(服务端也是netty nio), grpc客户端照样使用netty nio (服务端是 web 比如tomcat nio). lettuce有办法对应请求和响应, 所以客户端也是省连接使用netty nio (服务端是redis. 从客户端请求的角度来看, 服务端可以看成是单线程的, 因为redis协议和http1.1一样, 响应报文本身是没能力去对应请求的), 就算使用单个连接也很强
ps:
HTTP2:当使用 HTTP2 进行并发请求时,每个请求都会对应一个唯一的标识符,称为 Stream ID。请求和响应之间的对应关系是通过 Stream ID 来建立的。请求和响应的 Stream ID 是由客户端和服务器共同协商的,通过 HTTP2 协议中的流控制机制来实现。具体来说,客户端每次发出请求时都会带上一个唯一的 Stream ID,服务器在对应的响应报文中携带相同的 Stream ID,以此来建立请求和响应之间的对应关系。需要注意的是,使用 HTTP2 时不需要手动添加 Connection 和 Keep-Alive 字段,因为 HTTP2 中的多路复用技术会将多个请求和响应全部放在同一个 TCP 连接中,节省了连接的建立和关闭开销。HTTP1.1是请求-响应模型(根源也是没法对应请求和响应), 在一个连接上, 上一个请求的响应返回以前, 这个连接是不可以被使用的, 如果响应时间很长, 那就等着(不愿意耗着就关闭这个连接), 或者开连接池, 用别的连接. 别无他法