最简单的连接,短连接
短连接(short connnection)是相对于长连接而言的概念,指的是在数据传送过程中,只在需要发送数据时,才去建立一个连接,数据发送完成后,则断开此连接。
也就是说,如果一个连接建立之后,然后发送请求,接着就断开,那这个连接维持的时间是很短的,这个就是所谓的短连接。
长连接
但是短连接有一个很明显的问题,那就是每次发送请求,都必须要建立一个连接,然后再断开连接。
我们都知道,网络连接的建立是一个比较耗费资源的过程。
那么是不是可以建立好一个连接,然后不停的发送请求过来,系统再通过那个连接返回响应。这样就可以通过一个连接发送多个请求和返回多个响应,这就是所谓的长连接。
大量连接下使用长连接的问题
可是现在又有了一个新的问题,那就是当大量用户需要发送请求时,那么相当于每个用户都要跟系统建立一个长连接,对于系统来说就需要多个线程,每个线程需要去维护一个用户的长连接,然后通过这个连接跟一个用户不停的通信。
用户少的时候可能没什么问题,可是如果有几十万上百万的用户需要连接时,此时假设你的系统做了集群部署一共有100个服务实例,难道每个服务实例要维持1万个连接吗?
要是期望每个服务实例来维持上万个线程,那几乎是不可能的,所以这种模式最大的问题就在于这里,没法支撑大量连接。
Kafka 面临的挑战,大量连接
Kafka 作为大名鼎鼎的消息中间件,势必会面临大量连接的挑战,有大量生产者和消费者都要跟Kafka建立类似上面的长连接,然后基于一个连接,一直不停的通信。
那么 Kafka 是如何应对的呢?总不可能开几千上万个线程吧?
Reactor多路复用
Reactor多路复用模型,这就是Kafka采用的应对策略了。
Kafka Reactor的模型包括三种角色:
Acceptor
主要职责是监听客户端的连接请求,并建立和客户端的数据传输通道,然后为这个客户端指定一个processor,它的工作就到此结束了,这样它就可以去响应下一个客户端的连接请求了。
Processor
主要的职责就是负责从客户端读取数据和将响应返回给对应客户端,它本身就不处理具体的业务逻辑,每一个Processor都有一个Selector,用来监听多个客户端,因此可以费阻塞地处理多个客户端的读写请求,Processor会将数据放入请求队列中。
工作线程
主要的职责是从请求队列中提起请求,处理以后再将结果添加到响应队列中。
简单来说,就是通过一个acceptor线程,实现连接请求监听。该acceptor线程基于底层操作系统的支持可以监听大量连接。
如果有某个设备发送了建立连接的请求过来,那么那个线程就把这个建立好的连接交给processor线程。
每个processor线程同样会基于底层操作系统的支持监听多个连接,一个线程就可以负责维持多个连接。
如果某个连接发送了请求过来,那么这个processor线程就会把请求放到一个请求队列里去。
然后后台有一个线程池,这个线程池里有工作线程,会从请求队列里获取请求,处理请求,接着将请求对应的响应放到每个processor线程对应的一个响应队列里去。
最后,processor线程会把自己的响应队列里的响应发送回给客户端。
由上图我们可以看到,每个processor线程可以维持N个连接,并且所有的请求都会入队列排队,交给后台线程池来处理。
在这种模式下,每台机器只需要有限的线程数量就可以抗住大量的连接。