高性能即时通讯技术(或者说互联网)并发连接问题的解决思路
2021-08-20
1、前言
对于更关注高性能即时通讯技术(或互联网编程)的开发者来说,应该都对C10K问题(即单机并发连接问题)有所了解。 “C10K”的概念最早由Dan在他的个人网站上发表,即出自他的经典著作《The C10K(英文PDF版,中文译本)》。
如你所料,近10年来,通过高性能网络编程技术领域众多开发者的努力,C10K问题已经得到很好的解决,大家也开始关注并着手解决未来十年的问题。正确的C10M问题(即单机1000万并发连接问题,C10M相关技术的讨论和学习将在本系列文章的下一部分开始,本文不再深入介绍)。
虽然C10K问题已经得到妥善解决,但对于即时通讯应用(或其他网络编程)的开发者来说,研究C10K问题还是有很大的价值的,因为技术的发展是有规律的,有线索可循。了解C10K问题及其解决方案,通过对他人的推论,或许能为你以后解决类似问题提供更多的参考思路和实践思路。而这正是写这篇文章的目的。
2、学习交3、C10K系列文章
本文是C10K系列题的第二篇,大致内容如下:
4、C10K 提问者
丹:软件工程师
目前在美国洛杉矶工作,目前受雇于公司。我从1978年开始从事计算机编程。我是.0的作者,管理员,也是(一个让gcc/编译器更容易使用的工具套件)的作者。发表著名的《The C10K》技术文章,是Java JSR-51规范的提交者网络编程技术实验2,参与了Java平台的NIO和文件锁的编译,参与了NAT穿越(P2P打洞)技术的描述在 RFC 5128 标准和定义中。
5、C10K 问题的根源
大家都知道,互联网的基础是网络通信。早期的互联网可以说是小团体的集合。互联网不够普及,用户也不多。一台服务器同时有100个用户在线,估计当时是大型应用,所以C10K是没有问题的。互联网的爆发应该是在www、浏览器和雅虎出现之后。最早的互联网叫做Web1.0。互联网的大部分使用场景是下载一个HTML页面,用户在浏览器中查看页面上的信息。这段时间没有C10K问题。
Web2.0 时代不同了。一方面,渗透率大幅提升,用户群呈指数级增长。另一方面,互联网不再是单纯的浏览万维网页面,逐渐开始交互,应用的逻辑也变得更加复杂。从简单的表单提交到即时通讯和在线实时交互,C10K的问题都体现出来了。向上。由于每个用户都必须与服务器保持TCP连接才能进行实时数据交互,因此像这样的网站同时的TCP连接数很可能超过1亿。
早期的腾讯QQ也面临C10K的问题,不过他们使用UDP的原始包交换协议来实现这一点。这个问题被绕过了。当然,过程一定是痛苦的。如果当时有技术,肯定会用TCP。众所周知,后来的手机QQ和微信都采用了TCP协议。
其实当时有异步模式,比如:/poll模式,这些技术都有一定的缺点:比如最大不能超过1024、poll,没有限制,但是每次接收数据,需要遍历每个连接,查看哪个连接有数据请求。
这时候,问题来了。原始服务器基于进程/线程模型。对于新的 TCP 连接,需要分配一个进程(或线程)。而进程是操作系统最昂贵的资源,一台机器不能创建多个进程。如果 C10K 必须创建 10,000 个进程,那么操作系统无法在单机上承担它(通常效率低下甚至完全瘫痪)。如果采用分布式系统,维持1亿用户在线需要10万台服务器,成本巨大。只有像雅虎这样的巨头!雅虎有财力购买这么多服务器。
基于以上考虑,如何突破单机性能的局限,是高性能网络编程必须直接面对的问题。这些局限和问题首先由Dan进行了总结总结,并首次系统地分析并提出了解决方案。后来,这种常见的网络现象和技术限制被称为 C10K 问题。
6、技术C10K问题解读
C10K 问题的最大特点是,如果一个程序设计得不好,其性能与连接数和机器性能之间的关系往往是非线性的。
例如:如果不考虑C10K问题,一个基于经典的程序在旧服务器上可以很好地处理1000并发吞吐量,但在2倍性能的新服务器上往往无法处理并发2000吞吐量。 这是因为当策略不当时,大量操作的消耗与当前连接数n线性相关。单个任务的资源消耗与当前连接数之间的关系将为 O(n)。服务程序需要同时处理数以万计的I/O,累积的资源消耗会相当可观,这显然会导致系统吞吐量与机器性能不匹配。
以上是典型C10K问题的技术方面。这也是为什么大多数开发者可以轻松实现相同功能的原因,但是一旦放到大并发场景中,初级和高级开发者的技术实现相同功能的实际应用效果就会体现出来。完全不一样。
所以,一些在大并发方面没有太多实践经验的技术同行实现了即时通讯应用等网络应用。所谓的理论负载声称可以支持数万、数十万甚至数百万的单机。情况经不起考验和考验。
7、C10K 问题的本质
C10K 问题本质上是操作系统问题。对于Web1.0/2.0时代的操作系统,传统的同步阻塞I/O模型是一样的,处理方式是per。并发10K和100的区别关键在于CPU。
创建的进程线程过多,数据拷贝频繁(缓存I/O,内核拷贝数据到用户进程空间,阻塞),进程/线程上下文切换消耗大,导致操作系统崩溃。这就是C10K问题的本质!
可以看出,解决C10K问题的关键是尽可能减少CPU等核心计算资源的消耗,从而挤压单台服务器的性能,突破C10K中描述的瓶颈问题。
8、C10K 问题解决讨论
解决这个问题,从纯网络编程技术来看,主要有两个思路:
8.1 思路一:每个进程/线程处理一个连接
这个想法是最直接的。但是,由于应用进程/线程会占用相当多的系统资源,并且多进程/线程的管理会给系统带来压力,因此该方案没有很好的可扩展性。
所以这个想法在服务器资源不够丰富的情况下是不可行的。即使资源足够丰富,效率也不够高。总之,这个思路的技术实现会造成资源占用过多网络编程技术实验2,扩展性差。
8.2 思路二:每个进程/线程同时处理多个连接(IO复用)
IO 多路复用可以分为很多技术实现。下面我们来一一看看以下实现的优缺点。
● 实现方法一:传统思维最简单的方法是将每个连接一个一个循环处理,每个连接对应一个。当他们都有数据时,这种方法是可行的。但是当应用程序读取某个文件数据失败时,整个应用程序会阻塞在这里等待文件句柄,即使其他文件句柄,也无法进一步处理。
实现总结:直接循环处理多个连接。
问题总结:任何文件的文件句柄不成功都会阻塞整个应用程序。
● 实现2:解决上述阻塞问题,思路很简单。如果我在阅读之前检查文件句柄的状态,我会处理它。这个问题解决了吗?所以有一个计划。使用结构告诉内核同时监视多个文件句柄。当文件句柄的状态发生变化(例如,句柄从不可用变为可用)或超时时,调用将返回。之后,应用程序可以使用它来一一检查哪个文件句柄状态发生了变化。这样,小规模的连接问题不大,但是当连接数大(文件句柄数大)时,一一查看状态就很慢。因此,托管句柄通常有一个上限 ()。同时,在使用中,因为只有一个字段记录关注点和发生,所以每次调用前都要重新初始化结构体。
intselect(intnfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,structtimeval *timeout);
实现总结:如果有连接请求到达,再次检查处理。
问题总结:句柄上限+反复初始化+一一检查所有文件句柄状态效率不高。
● 实现方法三:poll主要解决的前两个问题:将需要关注的事件通过数组传递给内核,消除文件句柄的上限,用不同的字段标记感兴趣的事件和发生的事件避免重复初始化。
实现总结:设计新的数据结构,提高使用效率。
问题总结:一一查看所有文件句柄的状态效率不高。
● 实现 4:由于一一检查所有文件句柄的状态效率不高,因此很自然地在调用返回时仅向应用程序提供状态更改的文件句柄(最可能的数据),并且检查的效率是不是要高很多?这样的设计,适合大规模的应用场景。实验表明,当文件句柄数超过10个时,性能会优于和poll;当文件句柄数达到10K时,已经超过和轮询两个数量级。
实现总结:只返回状态改变的文件句柄。
问题总结:依赖特定的平台()。
因为它是互联网公司中使用最多的操作系统,所以它已经成为C10K、高并发、高性能、异步和非阻塞技术的代名词。启动,启动,启动 IOCP,启动 /dev/poll。这些操作系统提供的功能旨在解决C10K问题。该技术的编程模型是异步非阻塞回调,也可以称为事件驱动、事件轮询()。 ,, Node.js 这些都是时代的产物。
● 实现5:由于,IOCP每个接口都有自己的特点,程序移植非常困难,所以需要对这些接口进行封装,使其易于使用和移植,库就是其中之一。跨平台,封装底层平台的调用,提供统一的API,但底层会自动选择不同平台上合适的调用。根据官网介绍,该库提供了以下功能: 当文件描述符的特定事件(如可读、可写或错误)发生,或发生定时事件时,会自动执行用户指定的回调函数来处理事件。目前,支持以下接口 /dev/poll,,,, poll 和 。内部事件机制完全基于所使用的接口。所以它很容易移植,也使得它的可扩展性很容易。目前,它已在以下操作系统中编译通过:BSD、Mac OS X 和.使用该库进行开发非常简单,易于移植到各种unix平台。使用该库的简单程序如下:
9、参考资料
[1] 为什么QQ用的是UDP协议而不是TCP协议?
[2]手机IM/推送系统的协议选择:UDP还是TCP?
[3] 高性能网络编程经典:《The C10K(英文)》【附件下载】
[4] 高性能网络编程(一):单台服务器可以有多少并发TCP连接
[5]《C10K(英文在线阅读、英文PDF下载、中文翻译)》
[6] 搜狗实验室技术交流文档《C10K问题讨论》().pdf (350.83 KB)
[7]【浅显易懂】深入理解TCP协议(上):理论基础
[8] 【浅显易懂】深入理解TCP协议(二):RTT、滑动窗口、拥塞处理
[9]《TCP/IP详解第一卷:协议(在线阅读版)》