Nginx中的C10K问题和事件驱动模型

C10K问题

在传统的同步阻塞处理模型中,当创建的进程或线程过多时,缓存I/O、内核将数据拷贝到用户进程空间、阻塞,进程/线程上下文切换消耗大,简而言之 ,C10K问题就是无法同时处理大量客户端(10,000)的网络套接字。

解决思路

  1. 每个连接创建一个进程或线程
  2. 一个进程或线程同时处理多个连接

多线程处理多连接

申请和管理多线程需要占用额外资源,扩展性差,如tomcat。

单线程处理多连接

select方式:使用fd_set结构体告诉内核同时监控那些文件句柄,使用逐个排查方式去检查是否有文件句柄就绪或者超时。该方式有以下缺点:文件句柄数量是有上线的,逐个检查吞吐量低,每次调用都要重复初始化fd_set。

poll方式:该方式主要解决了select方式的2个缺点,文件句柄上限问题(链表方式存储)以及重复初始化问题(不同字段标注关注事件和发生事件),但是逐个去检查文件句柄是否就绪的问题仍然没有解决。

epoll方式:该方式可以说是C10K问题的killer,他不去轮询监听所有文件句柄是否已经就绪。epoll只对发生变化的文件句柄感兴趣。其工作机制是,使用"事件"的就绪通知方式,通过epoll_ctl注册文件描述符fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd, epoll_wait便可以收到通知, 并通知应用程序。而且epoll使用一个文件描述符管理多个描述符,将用户进程的文件描述符的事件存放到内核的一个事件表中, 这样数据只需要从内核缓存空间拷贝一次到用户进程地址空间。而且epoll是通过内核与用户空间共享内存方式来实现事件就绪消息传递的,其效率非常高,但是epoll是依赖系统的(Linux)。

Nginx中支持的事件驱动模型

kqueue | rtsig | epoll | /dev/poll | select | poll | eventport

标准事件模型

Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll。

高级事件模型

/dev/poll适用于 Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+;

Eventport适用于 Solaris 10. 为了防止出现内核崩溃的问题, 有必要安装安全补丁;

Kqueue适用用于 FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X,使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃;

epoll适用于于Linux内核2.6版本及以后的系统。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章