C10K Problem

C10K problem是指如何让服务器能够支持10k并发,当然你可以买昂贵的服务器,但是还有更便宜的办法。
这是最著名的讲C10K问题的网页《The C10K Problem

在Linux下面,解决这个问题的技术首选当然是epoll啦,不过2.6以上kernel才支持...2.4的兄弟们打个patch吧。

epoll的接口非常简单,一共就三个函数:
1. int epoll_create(int size);
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
大家看看man就知道具体参数意思。

需要注意的是epoll有两个触发方式,类似于中断的两种触发方式:

  • 边缘触发(ET):只有fd的状态有变化才会触发event,唤醒epoll_wait,比如新数据到来

  • 水平触发(LT):类似传统的poll,只要有数据,epoll_wait就会成功

但是在epoll出现之前,大家都习惯于LT的模式,而据说epoll最开始设计的时候只有ET模式,而且第一版的实现也只有ET模式,ET虽然快,但是比较容易出错,epoll的man page给出如下的死锁情况:
假定A,B通讯,A给B发送了一个2K的message,B的epoll_wait将会成功返回,B开始读数据,但是只读1k的时候调用epoll_wait,这时epoll_wait将进入等待状态(因为fd没有新状态变化)。如果此时A还在等待B的response,那么AB将会进入死锁状态。
后来在大家的强烈要求下,才加入了LT模式...

在这之前大家做异步I/O,大部分使用select/poll,在内核里面slect和poll的实现都差不多的,都是用VFS的poll函数实现的(fs/select.c)。select最多只能同时处理1024个fd,poll的问题是每次调用都要拷贝pollfd,同时处理的fd越多,效率越低。而epoll避免了这个问题,只有有状态变化的fd才有通知。

其实有很多lib和framework已经帮大家做了很好的封装,比如ACE, ASIO, libevent等,大家看哪个顺手就拿来用吧,至于windows下,当仁不让的选择是完成端口。

下面是一个各种异步I/O方法的性能比较图,来自libevent:
libevent-benchmark.jpg


你可能感兴趣的:(problem,C10K)