Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1764701
  • 博文数量: 290
  • 博客积分: 10653
  • 博客等级: 上将
  • 技术积分: 3178
  • 用 户 组: 普通用户
  • 注册时间: 2007-10-24 23:08
文章存档

2013年(6)

2012年(15)

2011年(25)

2010年(86)

2009年(52)

2008年(66)

2007年(40)

分类: C/C++

2011-12-25 01:43:26


该站点还有不少好文章,推荐大家可以看看。。
© () | 原文链接:
编写 高并发响应Server 需要的异步IO技术(Asynchronous IO/non-blocking IO) Asynchronous I/O(non-blocking I/O)

同时有多个IO操作的情况下。异步I/O,又称为non-blocking I/0,是指程序的运行不需要等待IO完成之后才能够继续进行。(Asynchronous I/O, or non-blocking I/O, is a form of input/output processing that permits other processing to continue before the transmission has finished.)。

而同步I/O(也称为blocking I/O),程序运行需等待IO完成之后才能继续,在等待的这段时间可能被OS挂起(idle)。这样当该程序包含多个IO操作的话,程序运行的很大部分时 间浪费在了I/O等待上。比较常见的时候基于socket的server程序,如果采用同步的blocking mode,则无法有效地响应多个并发的client请求。

异步IO模型可以有效地提高程序的throughput, latency, responsiveness.

参考:, (how to configure operating systems and write code to support thousands of clients.)

异步IO的实现 多进程()/多线程(threading)

将程序的运行和IO操作分配给独立的进程来完成,这样各个进程之间相互独立互不影响。该方法的缺点是:进程的创建和运行是昂贵的(独立的内存空间和资源);且如各个进程执行的任务不独立,还需要构建进程间的通信。

loop style方法(select/poll)

select/poll loop通过循环loop地执行或系统调用,侦听指定IO(file descriptor包括socket)的状态变化,直到满足一定的条件(ready to read/write/error)或达到一定的时间(timeout expires)或获得指定的signal;然后根据select或poll的返回值,再次通过loop判断各个IO的状态,并采取对应的操作(read/write)。

该方法相比较多进程方法,可以以单进程实现多个IO的异步执行。但方法的缺点包括:

  • depends heavily on the Unix paradigm that “everything is a file”; any blocking I/O that does not involve a file descriptor will block the process.
  • The select loop also relies on being able to involve all I/O in the central select call; libraries that conduct their own I/O are particularly problematic in this respect.
  • 两者都比较慢(因为包含2个loop)poll and select are basically the same speed-wise: slow.

They both handle file descriptors in a linear way. The more descriptors you ask them to check, the slower they get. As soon as you go beyond perhaps a hundred file descriptors or so - of course depending on your CPU and hardware - you will start noticing that the mere waiting for file descriptor activity and the following checking which file descriptor that it was, takes a significant time and becomes a bottle neck.

  • 可移植性(portability)差

由于select使用bitmask保存要侦听的file descriptor因此需要注意FD_SETSIZE的大小(不同的OS可能不同)。

另外select和poll方法2者的比较参看:, 。

多进程方法 和 select方法 实现并发响应的代码参看

poll实现并发响应的代码参看

event-based

event-based的方法不同于select/pool的event loop方法,它通过为希望侦听的IO(file descriptor)的指定event(或指定timeout)添加响应的callback function,这样当event产生或timeout时间到了,即会自动执行callback函数。

类似的方法有:(Linux Kernel after 2.5.44), kqueue(FreeBSD/NetBSD/OpenBSD/Darwin), /dev/poll(Solaris/HPUX), pollset(AIX), Event Completion(Solaris 10), I/O Completion Ports(Windows)等。

开发中可以使用各OS提供的API,如epoll。或使用一些event-based实现的库:libev和libevent。它们可用于编写可移植的event-based applications。例如libevent支持多种方法:/dev/poll, kqueue(2), select(2), poll(2), epoll(4) and Solaris's event ports.

epoll实现并发响应的代码参看

libevent库实现高并发socket server参看:

异步IO的应用:

异步IO/non-blocking非阻塞IO主要应用于高并发的IO请求,如client/server模式下,server要求对高并发的多 client进行快速响应。已经使用的:http server, database server, cache server等

比较经典的例子即:

Apache HTTP Server是process-based(forking or threaded),它使用loop style的select方法()。Nginx和Lighttpd等轻量级的http server使用了event-based的异步模式,如两者都使用了epoll方法()。 Apache遇到高并发请求,一方面需要创建大量的进程/线程耗费CPU时间,另一方面对每一个select的loop也是非常耗时的;而Nginx /Lighttpd等的epoll基于事件模型,单个请求不需要一个进程/线程陪伴请求整个生命期,抛弃了client请求与进程之间的一对一关系,大量 请求被os接管处理,而连接所耗资源相对较低,所以处理几万个连接是没有问题的。因此后者在高并发方面效果更好,具体比较

另外Memcached等也采用了epoll的网络IO模型。

因此,如果编写的server需要满足高并发请求建议使用event-based的IO模型,使用epoll或libevent库。

参考

阅读(2033) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~