高性能IO设计模式及其应用
2016-03-31 17:08
417 查看
转自:http://blog.sina.com.cn/s/blog_6a4c492f0100o6lr.html
想当然的服务器设计模式
服务器一般需要支持高性能的I/O,大并发等。先来看看大多数工程师准备自主开发一个服务器之前,自然而然想到的一些设计模式。准确的讲是实现的方法,远远谈不上设计模式。
第一种实现一个服务器的想当然的方法是,当有请求过来时,就fork一个子进程进行处理。下面这段示例代码是一个按照这种方法实现的服务器。这种方法易于理解,实现简单,如果并发量比较小,应该也能应付。但是如果是高并发的服务器就不理想了,因为fork大量的进程,并在不同的进程之间切换会消耗大量资源,造成服务器运行的效率下降。
int main(int argc, char **argv)
{
listenfd = Socket (AF_INET, SOCK_STREAM, 0);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
if ( (childpid = Fork()) == 0) {
process(connfd);
exit (0);
}
}
}
第二种实现服务器的方法是所谓的preforking,也就是预先创建”足够的“进程,每个进程通过accept阻塞在被侦听的端口上。也就是所谓的线程池的方法。这里不再示例代码,想了解细节请参照《UNIX Network Programming Volume
1, Third Edition》的30.6。
顺便提一下,第二种实现服务器的方法中,多个线程阻塞在同一个侦听端口上accept,存在所谓的 thundering
herd 问题,因此select(epoll,kqueue,iocp)就成了服务器编程的想当然的选择。
高性能I/O设计模式 - Reactor
Reactor设计模式中的要素如下:
Handles,也就是网络连接,文件句柄等。是事件源。
Synchronous Event Demultiplexer,同步事件的解复用(或者说派发),具体的比如select调用。比select更加高效的有linux下的epoll,freebsd下的kqueue以及windows下的iocp(IO Completion
port)。
Initiation Dispatcher,注册、移除和分派事件处理句柄。
Event Handler,就是事件处理句柄。
结合上面的描述,给出来自参考资料[3]图片如下:
无论是Reator还是Proactor,都包含了事件分离器和事件处理器。在接下来的对于Darwin视频服务器的分析中会发现其中也包含了事件分离器和事件处理器。
如下图所示,Reactor模式运行的顺序如下:
应用程序调用Initiation_Dispatcher注册一个Event_Handler,并给出对应的。Handler及事件类型。
注册完所有的Event_Handler后启动监听事件。
当有事件发生时,Synchronous Event Demultiplexer通知Initiation Dispatcher。
Initiation Dispatcher触发与Handler对应的Event Handler。
Reactor设计模式相关产品
Node.js
libev
libevent
boot.asio
ace
参考资料
Proactor和Reactor模式_继续并发系统设计的扫盲
QuickTime Streaming Server Modules Programming Guide。
An Object Behavioral Pattern for Demultiplexing and Dispatching Handles
for Synchronous Events
libevent,跨平台的Reactor的实现,地址: http://monkey.org/~provos/libevent/
libev,同libevent类似,据说性能稍好,地址: http://software.schmorp.de/pkg/libev.html
node.js
Architecture of a Highly Scalable NIO-Based
Server
想当然的服务器设计模式
服务器一般需要支持高性能的I/O,大并发等。先来看看大多数工程师准备自主开发一个服务器之前,自然而然想到的一些设计模式。准确的讲是实现的方法,远远谈不上设计模式。
第一种实现一个服务器的想当然的方法是,当有请求过来时,就fork一个子进程进行处理。下面这段示例代码是一个按照这种方法实现的服务器。这种方法易于理解,实现简单,如果并发量比较小,应该也能应付。但是如果是高并发的服务器就不理想了,因为fork大量的进程,并在不同的进程之间切换会消耗大量资源,造成服务器运行的效率下降。
int main(int argc, char **argv)
{
listenfd = Socket (AF_INET, SOCK_STREAM, 0);
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; ) {
connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);
if ( (childpid = Fork()) == 0) {
process(connfd);
exit (0);
}
}
}
第二种实现服务器的方法是所谓的preforking,也就是预先创建”足够的“进程,每个进程通过accept阻塞在被侦听的端口上。也就是所谓的线程池的方法。这里不再示例代码,想了解细节请参照《UNIX Network Programming Volume
1, Third Edition》的30.6。
顺便提一下,第二种实现服务器的方法中,多个线程阻塞在同一个侦听端口上accept,存在所谓的 thundering
herd 问题,因此select(epoll,kqueue,iocp)就成了服务器编程的想当然的选择。
高性能I/O设计模式 - Reactor
Reactor设计模式中的要素如下:
Handles,也就是网络连接,文件句柄等。是事件源。
Synchronous Event Demultiplexer,同步事件的解复用(或者说派发),具体的比如select调用。比select更加高效的有linux下的epoll,freebsd下的kqueue以及windows下的iocp(IO Completion
port)。
Initiation Dispatcher,注册、移除和分派事件处理句柄。
Event Handler,就是事件处理句柄。
结合上面的描述,给出来自参考资料[3]图片如下:
无论是Reator还是Proactor,都包含了事件分离器和事件处理器。在接下来的对于Darwin视频服务器的分析中会发现其中也包含了事件分离器和事件处理器。
如下图所示,Reactor模式运行的顺序如下:
应用程序调用Initiation_Dispatcher注册一个Event_Handler,并给出对应的。Handler及事件类型。
注册完所有的Event_Handler后启动监听事件。
当有事件发生时,Synchronous Event Demultiplexer通知Initiation Dispatcher。
Initiation Dispatcher触发与Handler对应的Event Handler。
Reactor设计模式相关产品
Node.js
libev
libevent
boot.asio
ace
参考资料
Proactor和Reactor模式_继续并发系统设计的扫盲
QuickTime Streaming Server Modules Programming Guide。
An Object Behavioral Pattern for Demultiplexing and Dispatching Handles
for Synchronous Events
libevent,跨平台的Reactor的实现,地址: http://monkey.org/~provos/libevent/
libev,同libevent类似,据说性能稍好,地址: http://software.schmorp.de/pkg/libev.html
node.js
Architecture of a Highly Scalable NIO-Based
Server
相关文章推荐
- dd命令使用详解
- JDBC中事务的整个流程!
- 数字排列大小
- JSTL 数据向上/下取整
- CentOS 7 安装过程
- poj 3261 Milk Patterns (后缀数组)
- 在SourceInsight中使用SourceMonitor对C语言程序进行度量,以及Kiviat图说明
- Cookies 和 Session的区别
- IIS与ASP.NET管道
- 滑屏框架
- 评审会议总结
- ebay的api的开发技术笔记
- CentOS下配置SSL
- Android Html交互_一_ 网页链接打开App页面
- android CoordinatorLayout使用
- ndk错误总结
- java 接口,抽象类 继承 归纳
- C++第二次作业
- *** Assertion failure in -[UITableView _configureCellForDisplay:forIndexPath:], /BuildRoot/Library/C
- SharePoint2013 IT Professional - Site Column& List Column