C10K问题
Posted OUYM
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C10K问题相关的知识,希望对你有一定的参考价值。
什么是C10K问题?
C10K问题全称是concurrent 10000 connection。是指服务器同时支持成千上万个客户端的问题
为什么会有C10K问题?
最初的服务器都是基于进程/线程模型的
,新到来一个TCP连接,就需要分配1个进程(或者线程)。而进程又是操作系统最昂贵的资源
,一台机器无法创建很多进程。如果是C10K就要创建1万个进程,那么操作系统是无法承受的
。如果是采用分布式系统,维持1亿用户在线需要10万台服务器,成本巨大,也只有Facebook,Google,雅虎才有财力购买如此多的服务器。这就是C10K问题的本质
。
解决方案
解决这一问题,主要思路有两个:一个是对于每个连接处理分配一个独立的进程/线程;另一个思路是用同一进程/线程来同时处理若干连接
。
(1)每个进程/线程处理一个连接
这一思路最为直接。但是由于申请进程/线程会占用相当可观的系统资源,同时对于多进程/线程的管理会对系统造成压力,因此这种方案不具备良好的可扩展性。
因此,这一思路在服务器资源还没有富裕到足够程度的时候,是不可行的;即便资源足够富裕,效率也不够高。
问题:资源占用过多,可扩展性差。
(2)每个进程/线程处理多个连接(IO多路复用)
-
传统思路
最简单的方法是循环挨个处理各个连接,每个连接对应一个 socket
,当所有 socket 都有数据的时候,这种方法是可行的。但是当应用读取某个 socket 的文件数据不 ready 的时候,
整个应用会阻塞在这里等待该文件句柄
,即使别的文件句柄 ready,也无法往下处理。思路:直接循环处理多个连接。
问题:任一文件句柄的不成功会阻塞住整个应用。
-
select
要解决上面阻塞的问题,思路很简单,如果我在读取文件句柄之前,
先查下它的状态,ready 了就进行处理,不 ready 就不进行处理
,这不就解决了这个问题了嘛?于是有了 select 方案。
用一个 fd_set 结构体来告诉内核同时监控多个文件句柄,当其中有文件句柄的状态发生指定变化(例如某句柄由不可用变为可用)或超时,则调用返回
。之后应用可以使用 FD_ISSET 来逐个查看是哪个文件句柄的状态发生了变化
。这样做,
小规模的连接问题不大,但当连接数很多(文件句柄个数很多)的时候,逐个检查状态就很慢了
。因此,select 往往存在管理的句柄上限(FD_SETSIZE)
。同时,在使用上,因为只有一个字段记录关注和发生事件,每次调用之前要重新初始化 fd_set 结构体
。int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
思路:有连接请求抵达了再检查处理。
问题:句柄上限+重复初始化+逐个排查所有文件句柄状态效率不高。
-
poll
poll 主要解决 select 的前两个问题:
通过一个 pollfd 数组向内核传递需要关注的事件消除文件句柄上限
,同时使用不同字段分别标注关注事件和发生事件,来避免重复初始化
。int poll(struct pollfd *fds, nfds_t nfds, int timeout);
思路:设计新的数据结构提供使用效率。
问题:逐个排查所有文件句柄状态效率不高。
-
epoll
既然逐个排查所有文件句柄状态效率不高,很自然的,
如果调用返回的时候只给应用提供发生了状态变化(很可能是数据 ready)的文件句柄
,进行排查的效率不就高多了么。epoll 采用了这种设计,适用于大规模的应用场景。
实验表明,
当文件句柄数目超过 10 之后,epoll 性能将优于 select 和 poll;当文件句柄数目达到 10K 的时候,epoll 已经超过 select 和 poll 两个数量级
。int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
思路:只返回状态变化的文件句柄。
问题:依赖特定平台(Linux)。
因为Linux是互联网企业中使用率最高的操作系统,
Epoll就成为C10K killer、高并发、高性能、异步非阻塞这些技术的代名词了
。FreeBSD推出了kqueue,Linux推出了epoll,Windows推出了IOCP,Solaris推出了/dev/poll。这些操作系统提供的功能就是为了解决C10K问题
。epoll技术的编程模型就是异步非阻塞回调
,也可以叫做Reactor,事件驱动,事件轮循(EventLoop)。nginx,libevent,node.js这些就是Epoll时代的产物。select、poll、epoll具体原理详解,请参见:《聊聊IO多路复用之select、poll、epoll详解》。
更多详见原文:http://blog.csdn.net/wangtaomtk/article/details/51811011
以上是关于C10K问题的主要内容,如果未能解决你的问题,请参考以下文章