暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【系统架构设计】支持百万级连接的系统,怎么如何架构设计?

也输思雪计算机之路 2021-10-18
1066

如何设计一个支撑百万甚至千万连接的高并发系统?比如rpc系统,消息中间件系统?

  • 缘起

  • 长连接

  • reactor多路复用模型

  • 总结

缘起

昨晚刷抖音,看到一个视频,说进厂累死了,就想到了著名的“流水线”模型,打算写一个“流水线”模型的起始系列文章(后续更新,会以1769年,乔赛亚·韦奇伍德 陶瓷工厂为起源,沿着工业1.0到到4.0,借着汽车行业展开)(喂,这是计算机,你讲啥玩意儿呢?)(流水线模型我不信你没听过,并发编程模型之一,用处可多得很),所以就在找这种工厂装配线的视频好讲述一些,找到一个百奇的,看到一处呈现分支的地方,所以就想到了今天的话题“支持百万连接的系统架构设计”。

ps:第一张图那里就是启发点

如果我们的系统需要支撑百万级甚至千万级的连接,该怎么办?假设我们的一个系统,作为一个服务会与很多外部系统调用,那它怎么和其他外部系统交互呢?也就是如何通信?

答:tcp连接

长连接

外部系统每次请求我们系统,都需要重新tcp连接,建立连接->发送数据->响应数据->断开连接,外部系统请求我们系统,做了很多的重复性操作:建立连接和断开连接,而这两个又是很好资源的操作,那有没有办法不做重复的建立连接和断开连接操作呢?这样的话可以节省出维护连接的资源(时间和cpu)。这就是长连接

使用长连接,外部系统和我们系统之间只需建立一次连接即可,后续都是用这个连接来传递数据,然后再释放。流程就会变成:建立连接->发送数据->响应数据->发送数据->响应数据。。。->断开连接。

这样确实省了维护连接的资源,但我们分析下,假设我们的系统使用的集群,共计100台,那么平均每台服务器需要承受1万连接数,一个连接需要一个线程来维护(你服务端始终需要一个线程循环地从socket中获取请求,然后处理,再响应),那么需要1万个线程维护。

开1万个线程?这服务器能行吗?

当然不行,一般服务器配置为4和8G的通用服务器,顶多支持100到200百cpu就负荷很高了,最优承受50到60线程。

那我可以加服务器配置啊,再不行,我再搞集群部署。(行啊,你有钱)

结合成本等考虑,我们可以换个想法,分析下,上面是一个线程处理一个连接,也就是管理一个连接,那要是我一个线程管理多个连接呢?不就可以了吗?

答:reactor多路复用模型

reactor多路复用模型

提到多路复用,其实最早是计算机网络系统中的实施的,传输媒体的容量(或者带宽)往往会大于传输单一信号的需求,所以为了有效地利用(物尽其用),所以想用一条信道同时传输多路信号,这就是多路复用技术(分为频分多路和时分多路,频分多路是根据信号的频谱来分信道,也即是分成小的路线,同一时间点信号频率不同,可以说是并行对的;而时分多路则是划分时间片轮流分配信道公信号使用【有点像cpu时间片轮转】,可以说是并发的)。

你说上面这些干嘛?这里的一个线程管理多个连接,就是类似于时分多路复用,因为他会按照时间来依次管理连接(同一时刻只有只有一个连接在被线程管理)。

那我们还可以继续分啊比如两次复用,再让一个总的线程来管理这些管理连接的线程(感觉有点类似socket中的accept方法吧,对这个感兴趣可以看看我GitHub上的压力测试工具)。那然后我们可以再利用队列来分解(为什么?异步处理,及时响应啊,管理连接的线程不处理请求的任务,这样可以快速返回,再继续监听连接,快速高效【这点还是想socket的accept方法模式】,可以不用队列吗?可以啊,随便都行,只要能存下连接的请求内容就行。),最后用一个工作线程从请求队列中读取处理(可以考虑用工作线程池分摊处理),最后将结果放回到管理连接的线程的响应队列中,管理连接线程再从响应队列取出结果即可,最后响应外部系统结果。

系统架构如下图(可以好好看下):

这样的话,那我们这服务器开50到60个线程,就可以支持1万的连接了(比如我开40个processor线程,每个processor线程管理1000连接,工作线程池放10个处理线程,加上acceptor,一共51个线程),当然这其中还牵涉很多东西,本文主要是提供架构设计思路(架构设计,思想先行),具体实施后续有机会接着详解。

总结

本文主要讲了支持百万连接的系统架构设计,其实最主要的点就是“多路复用”,希望能对你有所帮助。

ps:本文会是后续“RPC系统架构设计”系列的基础点之一

点个赞吧~~~~~~

关注我,不迷路


文章转载自也输思雪计算机之路,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论