高性能网络编程 - The C10K problem 以及 网络编程技术角度的解决思路

news2024/11/25 17:18:42

文章目录

  • C10K
  • C10K的由来
  • C10K问题在技术层面的典型体现
  • C10K问题的本质
  • C10K解决思路
    • 思路一:每个进程/线程处理一个连接
    • 思路二:每个进程/线程同时处理多个连接(IO多路复用)
      • ● 实现方式1:直接循环处理多个连接
      • ● 实现方式2: select
      • ● 实现方式3: poll
      • ● 实现方式4: epoll
      • ● 实现方式5: libevent

在这里插入图片描述


C10K

在这里插入图片描述

英文地址: http://www.kegel.com/c10k.html

中文地址: https://www.oschina.net/translate/c10k

C10K是指单机1万网络并发连接和数据处理能力。
C10M是指单机1000万网络并发连接和数据处理能力


C10K的由来

众所周知,互联网的基础是网络通信,早期的互联网规模有限,只涉及小规模用户群体。在这个阶段,互联网的用户数量相对较少,一台服务器同时在线100个用户已经算是大规模应用了,因此并没有面临所谓的C10K难题。

互联网的爆发期可以追溯到出现www网站、浏览器和雅虎等平台之后。早期互联网被称为Web1.0时代,主要用于下载HTML页面,用户通过浏览器查看网页上的信息,而不需要进行复杂的实时交互。在这个时期,并不需要解决C10K问题。

然而,随着Web2.0时代的到来,情况发生了变化。一方面,互联网的普及率大幅提高,用户数量呈几何级增长。另一方面,互联网不再局限于简单的网页浏览,而是逐渐变为互动的平台,应用程序的逻辑也变得更加复杂,从简单的表单提交发展到了实时通信和在线实时互动。正是在这个背景下,C10K问题开始显现出来。因为每个用户都需要与服务器保持TCP连接以进行实时数据交互。

早期的腾讯QQ也遇到了C10K问题,不过他们采用了UDP这种原始的包交换协议,绕过了这一难题,尽管过程相当具有挑战性。如果当时已经有epoll技术,他们很可能会选择使用TCP。众所周知,后来的手机QQ和微信都采用了TCP协议。

实际上,当时也有一些异步模型,例如select和poll模型,但它们都存在一些限制。比如,select模型的最大连接数不能超过1024,而poll没有这个限制,但每次需要遍历每个连接以检查哪个连接有数据请求。

这时候出现了一个关键问题:最初的服务器基于进程/线程模型,每当有新的TCP连接时,就需要分配一个新的进程或线程。然而,进程是操作系统中最昂贵的资源之一,因此一台机器无法同时创建大量进程。如果要应对C10K问题,可能需要创建上万个进程,这对单台机器来说是难以承受的,效率低下甚至可能导致系统崩溃。如果采用分布式系统,要维护上亿用户的在线连接可能需要上万台服务器,成本巨大 。

鉴于上述情况,如何突破单机性能的限制成为高性能网络编程不得不面对的问题。这些限制和问题最早由Dan Kegel总结和归纳,他首次系统地分析并提出了解决方案。后来,这些普遍存在的网络现象和技术限制都被广泛称为C10K问题。
在这里插入图片描述


C10K问题在技术层面的典型体现

C10K问题的主要特点在于,当程序设计不够精良时,其性能与连接数量和机器性能之间的关系通常表现为非线性

举例来说,如果没有考虑C10K问题,一个经典基于select的程序在旧服务器上可以良好地处理1000个并发连接,但在性能翻倍的新服务器上却常常无法处理2000个并发连接。这是因为在策略不当的情况下,大量操作的开销与当前连接数n成线性相关,导致单个任务的资源消耗与当前连接数之间呈线性关系,即O(n)。对于服务程序来说,需要同时处理数以万计的套接字I/O操作,累积下来的资源开销相当可观,这显然会导致系统吞吐量无法与机器性能相匹配。

这便是C10K问题在技术层面的典型体现。这也解释了为什么大多数开发人员可以相对容易地从功能上实现相同的功能,但一旦应用到高并发场景中,初级开发人员和高级开发人员的技术实现会产生截然不同的实际应用效果。

因此,一些缺乏大规模并发实践经验的技术从业者,例如那些开发即时通讯应用等网络应用的人,往往在没有经受检验和考验的情况下声称其应用能够在单台服务器上支持上万、上十万甚至上百万的用户,这种说法常常难以经受实际验证。

在这里插入图片描述


C10K问题的本质

C10K问题本质上与操作系统的设计和性能密切相关。在Web1.0和Web2.0时代,传统的同步阻塞I/O模型在操作系统中普遍存在,处理方式都以"requests per second"为标准,而区分处理10K并发和100并发的关键在于CPU性能。

当创建大量进程和线程时,会导致数据频繁拷贝(包括缓存I/O、内核将数据从内核空间拷贝到用户进程空间等),并且进程/线程上下文切换的成本较高。这导致操作系统面临巨大的挑战,可能因此崩溃,这正是C10K问题的本质所在。

因此,解决C10K问题的关键在于尽可能减少对CPU等核心计算资源的消耗,从而充分发挥单台服务器的性能,以突破C10K问题所描述的性能瓶颈。这可以通过采用异步I/O模型、事件驱动编程、使用高效的多路复用技术如epoll等,以及优化操作系统内核等方式来实现。通过这些方法,可以显著提高服务器的吞吐量,减少资源消耗,从而解决C10K问题。

在这里插入图片描述


C10K解决思路

要解决这一问题,从纯网络编程技术角度看,主要思路有两个

  • 对于每个连接处理分配一个独立的进程/线程
  • 用同一进程/线程来同时处理若干连接

思路一:每个进程/线程处理一个连接

这一思路最为直接。但是由于申请进程/线程会占用相当可观的系统资源,同时对于多进程/线程的管理会对系统造成压力,因此这种方案不具备良好的可扩展性。

因此,这一思路在服务器资源还没有富裕到足够程度的时候,是不可行的。即便资源足够富裕,效率也不够高。

总之,此思路技术实现会使得资源占用过多,可扩展性差。


思路二:每个进程/线程同时处理多个连接(IO多路复用)

IO多路复用从技术实现上又分很多种,我们逐一来看看下述各种实现方式的优劣。

● 实现方式1:直接循环处理多个连接

传统思路最简单的方法是循环挨个处理各个连接,每个连接对应一个 socket,当所有 socket 都有数据的时候,这种方法是可行的。但是当应用读取某个 socket 的文件数据不 ready 的时候,整个应用会阻塞在这里等待该文件句柄,即使别的文件句柄 ready,也无法往下处理。

实现小结:直接循环处理多个连接。
问题归纳:任一文件句柄的不成功会阻塞住整个应用。


● 实现方式2: select

select要解决上面阻塞的问题,思路很简单,如果我在读取文件句柄之前,先查下它的状态,ready 了就进行处理,不 ready 就不进行处理,这不就解决了这个问题了嘛?

于是有了 select 方案。用一个 fd_set 结构体来告诉内核同时监控多个文件句柄,当其中有文件句柄的状态发生指定变化(例如某句柄由不可用变为可用)或超时,则调用返回。之后应用可以使用 FD_ISSET 来逐个查看是哪个文件句柄的状态发生了变化。这样做,小规模的连接问题不大,但当连接数很多(文件句柄个数很多)的时候,逐个检查状态就很慢了。

因此,select 往往存在管理的句柄上限(FD_SETSIZE)。同时,在使用上,因为只有一个字段记录关注和发生事件,每次调用之前要重新初始化 fd_set 结构体。

intselect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

实现小结:有连接请求抵达了再检查处理。
问题归纳:句柄上限+重复初始化+逐个排查所有文件句柄状态效率不高。


● 实现方式3: poll

poll 主要解决 select 的前两个问题:通过一个 pollfd 数组向内核传递需要关注的事件消除文件句柄上限,同时使用不同字段分别标注关注事件和发生事件,来避免重复初始化。

实现小结:设计新的数据结构提供使用效率。
问题归纳:逐个排查所有文件句柄状态效率不高。


● 实现方式4: epoll

poll既然逐个排查所有文件句柄状态效率不高,很自然的,如果调用返回的时候只给应用提供发生了状态变化(很可能是数据 ready)的文件句柄,进行排查的效率不就高多了么。

epoll 采用了这种设计,适用于大规模的应用场景。实验表明,当文件句柄数目超过 10 之后,epoll 性能将优于 select 和 poll;当文件句柄数目达到 10K 的时候,epoll 已经超过 select 和 poll 两个数量级。

实现小结:只返回状态变化的文件句柄。
问题归纳:依赖特定平台(Linux)。

因为Linux是互联网企业中使用率最高的操作系统,Epoll就成为C10K killer、高并发、高性能、异步非阻塞这些技术的代名词了。FreeBSD推出了kqueue,Linux推出了epoll,Windows推出了IOCP,Solaris推出了/dev/poll。这些操作系统提供的功能就是为了解决C10K问题。epoll技术的编程模型就是异步非阻塞回调,也可以叫做Reactor,事件驱动,事件轮循(EventLoop)。Nginx,libevent,node.js这些就是Epoll时代的产物。


● 实现方式5: libevent

由于epoll, kqueue, IOCP每个接口都有自己的特点,程序移植非常困难,于是需要对这些接口进行封装,以让它们易于使用和移植,其中libevent库就是其中之一。

跨平台,封装底层平台的调用,提供统一的 API,但底层在不同平台上自动选择合适的调用。

按照libevent的官方网站,libevent库提供了以下功能:当一个文件描述符的特定事件(如可读,可写或出错)发生了,或一个定时事件发生了,libevent就会自动执行用户指定的回调函数,来处理事件。

目前,libevent已支持以下接口/dev/poll, kqueue, event ports, select, poll 和 epoll。Libevent的内部事件机制完全是基于所使用的接口的。

因此libevent非常容易移植,也使它的扩展性非常容易。目前,libevent已在以下操作系统中编译通过:Linux,BSD,Mac OS X,Solaris和Windows。使用libevent库进行开发非常简单,也很容易在各种unix平台上移植。

一个简单的使用libevent库的程序如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1186654.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

启动Hbase出现报错

报错信息:slave1:head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewanggiqi-regionserver-slavel.out’ for reading: No such file or direslave2: head: cannot open/usr/local/hbase-2.3.1/bin/../logs/hbasewangqiqi-regionserver-slave2.out’ for …

OpenCV 图像复制和图像区域读写

图像复制 共享数据, 使用 new Mat(srcMat, ...) 和 newMatsrcMat 生成新的Mat都和原Mat共享数据, 也就是说如果修改某一Mat,其他Mat也会随之改变复制全新的Mat, 使用CopyTo() 和 Clone() 方法将生成一个全新的Mat, 新Mat和原Mat不共享数据. 图像区域和点的读写 区域读取: 通过s…

JavaEE初阶学习:Linux 基本使用和 web 程序部署

1.Linux的基本认识 Linux 是一个操作系统.(搞管理的系统) 和Windows都是同类产品~~ Linux 实际的场景: 1.服务器 2.嵌入式设备 3.移动端(手机)Android 其实就是Linux 1991年,还在读大学的 芬兰人 Linus Benedict Torvalds,搞了一个Linux 这样的系统0.01版,正式发布了~ 后…

[量化投资-学习笔记007]Python+TDengine从零开始搭建量化分析平台-布林带

布林带(Bollinger Bands)也称为布林通道、保力加通道,是由约翰布林格(John Bollinger)发明的技术分析指标。布林通道通常被用来确认资产价格波动范围。 布林通道是由三条平滑的曲线组成的趋势线图表,中线为…

HDPE双壁波纹管存在缺点,在选择使用时需要根据实际情况进行考虑

惠洁友情提醒HDPE双壁波纹管脆性较大:HDPE双壁波纹管的脆性较大,容易受到冲击和碰撞的影响,如果使用过程中出现破损或裂缝,可能会影响到其密封性能和使用寿命。 对温度敏感:HDPE双壁波纹管的性能受温度影响较大&#…

安全测试,接口返回内容遍历~

最近公司被人大量爬取数据,查了一下发现,用户主页接口,没有加用户登录校验,返回了用户的敏感信息有手机号和邮箱,其实这个接口是用不到这些信息的。再加上用户id是自增长的,所以很容易被别人爬取。 既然这…

【milkv】添加LCD屏GC9306

前言 本章介绍如何添加LCD屏GC9306驱动。 电路图 dts build\boards\cv180x\cv1800b_milkv_duo_sd\dts_riscv\cv1800b_milkv_duo_sd.dts &spi2 {status "okay";/delete-node/ spidev0;gc9306: gc93060{compatible "sitronix,gc9306";reg <0&g…

[PHP]得推跑腿O2O系统 v3.41

得推跑腿系统是一个以phpMySQL进行开发的主要针对本地跑腿服务的O2O系统&#xff0c;支持wap\\小程序\\App。 主要功能模块&#xff1a; 用户端&#xff1a; 1.跑腿任务发布 2.跑腿任务管理追踪 3.在线支付 4.常用地址管理 跑腿端&#xff1a; 1.跑腿任务抢单 2.跑腿员认证 3.…

Win11 Edge浏览器进入朔日考试系统(无纸化测评系统)的方法

Win11 Edge浏览器进入朔日考试系统&#xff08;无纸化测评系统&#xff09;的方法 笔记本型号&#xff1a;联想 使用浏览器&#xff1a;edge浏览器 操作系统&#xff1a;Windows11 网址&#xff1a;http://172.31.0.139/WZHEDU/ 注意:使用此方法打开edge浏览器会频繁出现弹窗&a…

第17章 反射机制

通过本章需要理解反射机制操作的意义以及Class类的作用&#xff0c;掌握反射对象实例化操作&#xff0c;并且可以深刻理解反射机制与工厂模式结合意义。掌握类结构反射操作的实现&#xff0c;并且可以通过反射实现类中构造方法、普通方法、成员属性的操作。掌握反射机制与简单J…

19.13 Boost Asio 发送TCP流数据

Boost框架中默认就提供了针对TCP流传输的支持&#xff0c;该功能可以用来进行基于文本协议的通信&#xff0c;也可以用来实现自定义的协议。一般tcp::iostream会阻塞当前线程&#xff0c;直到IO操作完成。 首先来看服务端代码&#xff0c;如下所示在代码中首先通过GetFileSize…

2023.11.08 homework

小学五年级数学

Vim编辑器学习

B站学习vim指令链接 1&#xff1a;vim下有两种模式&#xff0c;一种是命令模式&#xff0c;一种是编辑模式 2&#xff1a;命令到编辑模式&#xff0c;按键盘i&#xff0c;编辑到命令格式按Esc 3&#xff1a;&#xff1a;wq 保存并退出 &#xff1a;wq code.c保存并把文件命名为…

【机器学习基础】机器学习概述

目录 前言 一、机器学习概念 二、机器学习分类 三、机器学习术语 &#x1f308;嗨&#xff01;我是Filotimo__&#x1f308;。很高兴与大家相识&#xff0c;希望我的博客能对你有所帮助。 &#x1f4a1;本文由Filotimo__✍️原创&#xff0c;首发于CSDN&#x1f4da;。 &#x…

Mysql数据库 11.SQL语言 储存过程 下 储存过程管理和游标

一、存储过程管理 1.查询存储过程 查询所有储存过程 语法 show procedure status; 代码实现 #查询存储过程 show procedure status; 运行结果 加入条件查询储存过程 语法 show procedure status where db储存过程名; 代码实现 #查询带有条件的储存过程 查询名字为pro…

第五届泰迪杯数据分析技能赛B题源码图片分享

需要B题源码以及第六届带队”指导“请私信本人&#xff0c;团队包含技能赛双一等&#xff0c;数学建模省一&#xff0c;泰迪杯挖掘国一&#xff0c;研究生队友。 去年一等作品可视化图如下&#xff0c;私信获取源码

clickhouse通过java jdbc实现增删改查,保姆级教程

一、clickhouse是一款开源的用于在线分析处理查询(OLAP :Online Analytical Processing)MPP架构的列式存储数据库。 二、clickhouse可以做用户行为分析&#xff0c;流批一体 三、我们现在用java通过jdbc的方式来操作clickhouse 四、先安装clickhouse&#xff0c;安装资料自行…

长春理工大学漏洞报送证书

获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;主页 | 教育漏洞报告平台 兑换价格&#xff1a;10金币 获取条件&#xff1a;提交长春理工大学任意中危或以上级别漏洞

尚硅谷大数据项目《在线教育之实时数仓》笔记007

视频地址&#xff1a;尚硅谷大数据项目《在线教育之实时数仓》_哔哩哔哩_bilibili 目录 第9章 数仓开发之DWD层 P053 P054 P055 P056 P057 P058 P059 P060 P061 P062 P063 P064 P065 第9章 数仓开发之DWD层 P053 9.6 用户域用户注册事务事实表 9.6.1 主要任务 读…

kafka笔记要点和集群安装、消息分组、消费者分组以及与storm的整合机制

kafka笔记 1/kafka是一个分布式的消息缓存系统 2/kafka集群中的服务器都叫做broker 3/kafka有两类客户端&#xff0c;一类叫producer&#xff08;消息生产者&#xff09;&#xff0c;一类叫做consumer&#xff08;消息消费者&#xff09;&#xff0c;客户端和broker服务器之间…