当前位置: 首页 > 科技观察

如果你的系统需要支持百万连接,那么架构应该如何设计?

时间:2023-03-21 01:47:21 科技观察

1。究竟什么是连接?如果你现在有一个系统,它需要连接很多很多的硬件设备,这些硬件设备必须要和你的系统进行通信。那么,您如何与系统通信?首先他肯定会和你的系统建立连接,然后根据这个连接向你的系统发送请求。然后你的系统会给那个系统返回一个响应,最后大家一起断开连接,释放网络资源。那么我们就通过下图来感受下这个所谓的连接是什么概念吧。2、为什么每次发送请求都需要建立连接?但是大家看上图的时候是不是觉得有很大的问题。有什么问题?这就是为什么每次发送请求都要建立一个连接,然后又要断开一个连接?要知道,网络连接的建立和连接涉及到多次网络通信,本质上是一个资源密集型过程。所以我们完全没有必要每次发送请求都要建立连接和断开连接。我们完全可以建立一个连接,然后设备会不断发送请求,系统会通过那个连接返回响应。您可以多次通过连接发送请求和返回响应。这就是所谓的长连接。也就是说,如果建立连接,然后发送请求,然后断开连接,那么连接维持的时间很短,也就是所谓的短连接。那么如果一个设备与你的系统建立连接,然后通过这个连接不断发送请求和接收响应,你就可以避免不断创建和断开连接的开销。看看下面的图片来体验一下这个过程。图中两个连接之间有很多发送请求和接收响应的过程,这样可以用一个连接进行多次通信。3、长连接模式需要消耗大量的线程资源,现在问题又来了。长连接模式确实不错,但是如果每个设备都要和系统长期保持一个连接,那么系统就需要搞一个线程,这个线程需要维护一个设备的长连接,而然后通过这个连接与一个设备通信,接收别人发来的请求,并返回响应给别人。看下图,每个设备都要和系统保持一个连接,那么对于每一个设备连接,系统都会有一个独立的线程来维护这个连接。因为你必须有一个线程不断尝试从网络连接中读取请求,然后处理请求,最后将响应返回给设备。那么这种模式有什么缺点呢?劣势很明显。假设此时您有数百万台设备要连接到您的系统。假设您的系统有一个集群部署,总共有100个服务实例。每个服务实例需要维护10000个吗?Connection支持与10,000个设备通信?如果是这样,每个服务实例不就得维护10000个线程才能维护10000个连接吗?大家觉得这个靠谱吗?根据线上生产经验,4核8G标准服务的虚拟机,如果自己开发一两百个工作线程,CPU负载会非常高。最好的建议是使用几十个工作线程。几乎。所以指望每个服务实例维护几万个线程几乎是不可能的,所以这种模式最大的问题就是不能支持大量的连接数。4、Kafka遇到的问题:处理大量的客户端连接其实对于大名鼎鼎的消息系统Kafka,他也会面临同样的问题,因为他需要处理大量的客户端连接。有很多生产者和消费者都要和上面类似的Kafka建立一个长连接,然后基于一个连接不断的通信。比如生产者需要通过一个连接不断的向Kafka发送数据。那么Kafka会通过这个连接不断的向生产者返回响应。消费者也需要通过一个连接不断的从Kafka获取数据,而Kafka需要通过这个连接不断的返回数据给消费者。看下图,感受下Kafka的生产现场。那如果Kafka简单的按照这个架构来处理的话,如果你公司有几万、几十万个生产者或者消费者服务实例,Kafka集群有必要维护几万、几十万个连接吗?线程太多?同样,这是不现实的,因为线程是一种昂贵的资源,不可能在集群中使用那么多线程。5、Kafka的架构实践:Reactor多路复用针对这个问题,大名鼎鼎的Kafka采用的架构策略就是Reactor多路复用模型。简单来说,就是构建一个acceptor线程,基于底层操作系统的支持,实现连接请求监听。如果某个设备发出建立连接的请求,那么那个线程就会把建立的连接交给处理器线程。每个处理器线程会被分配N个多连接,一个线程可以负责维护N个多连接,同时也会根据底层操作系统的支持监听N个多连接请求。如果连接发送请求,则处理器线程将请求放入请求队列中。然后后台有个线程池。这个线程池中有工作线程,会从请求队列中获取请求,处理请求,然后将请求对应的响应放到每个处理器线程对应的响应队列中。最后,处理器线程将自己的响应队列中的响应发送回客户端。说了这么多,先上图吧。你可以通过看下图来理解上面的整个过程。6、优化后的架构如何支持大量连接?那么上面的优化架构是如何支持大量连接的呢?这实际上很容易。这里最关键的因素是处理器线程是一个人维护N个线程。基于底层操作系统特殊机制的支持,一个人可以监听N个连接请求。这是极其关键的一步。只需要这一步就可以让一个线程支持多个连接,而不需要一个线程支持一个连接。而那个处理器线程只接收请求和发送响应,所有的请求都会排队交给后台线程池处理。比如按100万个连接计算,如果有100台机器去处理,按照老模型,每台机器需要维护10000个线程来处理10000个连接。但是如果按照这种复用模式,可能就像一个10个处理器+40个线程的线程池,总共50个线程可以支持上万个连接。在这种模式下,每台机器有限的线程数可以承受大量的连接。所以其实我们在设计这种支持大量连接的系统的时候,可以参考这个架构,采用多路复用的方式设计,用几十个线程来处理上千个连接,最终实现百万连接的处理建筑学。