一、长链接
长连接是发送完一次tcp请求之后,连接不断开,可以继续发送。
但是此时由于请求没有唯一识别的标记,所以请求只能串行发送,即一个请求只有接到响应之后才能继续发送。
解决的是客户端与服务端频繁建立tcp连接带来的三次握手等开销问题。
并没有提升服务器的并发能力,对客户端的响应速度也没有特大的提升(因为仅仅省去了几次连接的建立开销)。
所以http1.1 采用了多链接的方式进一步提升,即每次建立多个长连接,并行去请求服务器。
这是因为http请求的协议头没有唯一标识的id字段,无法乱序发送请求,所以只能多开连接并行来提高速度,http2.0为报头添加唯一id后,采用了一个长连接,因为http请求的请求量不是很大,用一个连接乱序发送和多个连接同时发送效果的差不多的,还能节省多建立几个连接的开销(变相的提高了服务端的并发量----一个连接对应一个客户端,而不是多个连接对应一个客户端了)。
二、连接复用
连接复用,则是为每个请求加上了一个请求唯一id,这样将请求发送出去后,I/O线程可以直接返回,不用等待响应到达,可以直接发送下一个请求,请求与请求之间通过ID来区分。
实质上就是长链接,只是请求的实现方式不同,请求加了id可以乱序发送了。
主要作用还是节省频繁建立tcp连接的开销(长连接的作用),同时对于客户端来说,有没有提升客户端的并发量主要还是看I/O模型(或者说线程模型)。
如果一个连接可以供上层多个线程使用,那么就提高了并发,同时这也就相当于有了类似I/O多路复用的语意,即一个连接对应多个I/O线程,但是这样需要同步支持,否则数据就错乱了。所以,可以让一个连接对应一个I/O线程,然后采用reactive模型实现让一个I/O线程监听多个业务线程(而不是连接,思想是一致的)。
三、I/O复用
I/O复用主要是用来提升并发量的,由一个线程来监听多个连接,每个连接可以是短连接也可以采用长连接。
针对rpc场景的话,一般采用长连接,因为微服务之间网络通信特别频繁,如果采用短连接,连接的建立开销会成为网络瓶颈。
客户端采用NIO的意义是什么呢?让一个I/O线程监听多个和服务器的连接,在微服务场景下,很适用,因为一个微服务会和其他成百上千个微服务建立连接,这样可以用一个线程来接收所有的服务端的响应。
但是当客户端对外提供的微服务收到很多的并发访问的时候,客户端就相当于了一个服务器,它的并发量则主要受到它的服务线程的I/O模型的限制。
当客户端的瓶颈在于和服务端的交互的时候,那么BIO的方式就是采用连接池(此时服务端可以使用NIO,也可以使用BIO),NIO的方式则是自己根据reactive的思想来实现一个类似于NIO的框架,实现让一个I/O线程可以监听多个业务线程,如果一个线程处理不完,则就要用连接池的方式多建立几个连接。
四、总结
连接复用主要用来减少连接开销。对于并发量的提升主要看I/O模型,这不是连接复用决定的。
如果采用BIO的方式,那么就是连接池的方式。
如果采用NIO的方式,那么就是自己创建一个Reactive模型。
那么可不可以用reactive模型实现一个线程池呢?