高并发与C10K问题
C10k 问题的本质:
-
互联网的基础就是网络通信,最初的服务器都是基于进程/线程模型
-
新到来一个TCP连接,就需要分配1个进程(或者线程)。
-
进程又是操作系统最昂贵的资源,一台机器无法创建很多进程。
-
如果是C10K就要创建1万个进程,那么操作系统是无法承受的。
-
如果是采用分布式系统,维持1亿用户在线需要10万台服务器,成本巨大
解决方法:
-(1)每个进程/线程处理一个连接 资源占用过多,可扩展性差
-(2)每个进程/线程同时处理多个连接(IO多路复用)
IO多路复用:
select
同时监控多个文件句柄,有连接请求抵达了再检查处理。
缺点: 句柄上限
重复初始化
逐个排查所有文件句柄状态效率不高
poll
poll 主要解决 select 的前两个问题:
通过一个设计新的数据结构提供使用效率,消除文件句柄上限,
同时使用不同字段分别标注关注事件和发生事件,来避免重复初始化。
缺点:逐个排查所有文件句柄状态效率不高。
epoll
只返回状态变化的文件句柄
缺点: 依赖特定平台(Linux)
-
Epoll就成为C10K killer、高并发、高性能、异步非阻塞这些技术的代名词
-
文件句柄数目超过 10 之后,epoll 性能将优于 select 和 poll
-
当文件句柄数目达到 10K 的时候,epoll 已经超过 select 和 poll 两个数量级。
-
Nginx,libevent,node.js这些就是Epoll时代的产物。
协程coroutine
各个协程之间的切换,往往是用户通过代码来显式指定的(跟各种 callback 类似), 不需要内核参与,可以很方便的实现异步
协程是异步非阻塞的另外一种展现形式
生成器 yield,send 也是一种异步模型
greenlet 手动切换
gevent 自动切换,但是不识别 timesleep,socket的io阻塞
需要加上 from gevent import monkey;monkey.patch_all()放到文件的开头
注意:
-
协程 程序级别的切换
-
epoll 是操作系统级别的切换