Nginx的高并发得益于其采用了epoll模型,与传统的服务器程序架构不同,epoll是linux内核2.6以后才出现的。下面通过比较Apache和Nginx工作原理来比较。

传统Apache都是多进程或者多线程来工作,假设是多进程工作(prefork),apache会先生成几个进程,类似进程池的工作原理,只不过这里的进程池会随着请求数目的增加而增加。对于每一个连接,apache都是在一个进程内处理完毕。具体是 recv(),以及根据 URI 去进行磁盘I/O来寻找文件,还有 send()都是阻塞的。其实说白了都是 apche 对于套接字的I/O,读或者写,但是读或者写都是阻塞的,阻塞意味着进程就得挂起进入sleep状态,那么一旦连接数很多,Apache必然要生成更多的进程来响应请求,一旦进程多了,CPU对于进程的切换就频繁了,很耗资源和时间,所以就导致apache性能下了,说白了就是处理不过来这么多进程了。其实仔细想想,如果对于进程每个请求都没有阻塞,那么肯定效率会提高很多。

Nginx采用epoll模型,异步非阻塞。对于Nginx来说,把一个完整的连接请求处理都划分成了事件,一个一个的事件。比如accept(), recv(),磁盘I/O,send()等,每部分都有相应的模块去处理,一个完整的请求可能是由几百个模块去处理。真正核心的就是事件收集和分发模块,这就是管理所有模块的核心。只有核心模块地调度才能让对应的模块占用CPU资源,从而处理请求。拿一个HTTP请求来说,首先在事件收集分发模块注册感兴趣的监听事件,注册好之后不阻塞直接返回,接下来就不需要再管了,等待有连接来了内核会通知你(epoll的轮询会告诉进程),cpu就可以处理其他事情去了。一旦有请求来,那么对整个请求分配相应的上下文(其实已经预先分配好),这时候再注册新的感兴趣的事件(read函数),同样客户端数据来了内核会自动通知进程可以去读数据了,读了数据之后就是解析,解析完后去磁盘找资源(I/O),一旦I/O完成会通知进程,进程开始给客户端发回数据send(),这时候也不是阻塞的,调用后就等内核发回通知发送的结果就行。整个下来把一个请求分成了很多个阶段,每个阶段都很很多模块去注册,然后处理,都是异步非阻塞。异步这里指的就是做一个事情,不需要等返回结果,做好了会自动通知你。

可以举一个简单的例子来说明Apache的工作流程,我们平时去餐厅吃饭。餐厅的工作模式是一个服务员全程服务客户,流程是这样,服务员在门口等候客人(listen),客人到了就接待安排的餐桌上(accept),等着客户点菜(request uri),去厨房叫师傅下单做菜(磁盘I/O),等待厨房做好(read),然后给客人上菜(send),整个下来服务员(进程)很多地方是阻塞的。这样客人一多(HTTP请求一多),餐厅只能通过叫更多的服务员来服务(fork进程),但是由于餐厅资源是有限的(CPU),一旦服务员太多管理成本很高(CPU上下文切换),这样就进入一个瓶颈。
再来看看Nginx得怎么处理?餐厅门口挂个门铃(注册epoll模型的listen),一旦有客人(HTTP请求)到达,派一个服务员去接待(accept),之后服务员就去忙其他事情了(比如再去接待客人),等这位客人点好餐就叫服务员(数据到了read()),服务员过来拿走菜单到厨房(磁盘I/O),服务员又做其他事情去了,等厨房做好了菜也喊服务员(磁盘I/O结束),服务员再给客人上菜(send()),厨房做好一个菜就给客人上一个,中间服务员可以去干其他事情。整个过程被切分成很多个阶段,每个阶段都有相应的服务模块。我们想想,这样一旦客人多了,餐厅也能招待更多的人。

不管是Nginx还是Squid这种反向代理,其网络模式都是事件驱动。事件驱动其实是很老的技术,早期的select、poll都是如此。后来基于内核通知的更高级事件机制出现,如libevent里的epoll,使事件驱动性能得以提高。事件驱动的本质还是IO事件,应用程序在多个IO句柄间快速切换,实现所谓的异步IO。事件驱动服务器,最适合做的就是这种IO密集型工作,如反向代理,它在客户端与WEB服务器之间起一个数据中转作用,纯粹是IO操作,自身并不涉及到复杂计算。反向代理用事件驱动来做,显然更好,一个工作进程就可以run了,没有进程、线程管理的开销,CPU、内存消耗都小。

所以Nginx、Squid都是这样做的。当然,Nginx也可以是多进程 + 事件驱动的模式,几个进程跑libevent,不需要Apache那样动辄数百的进程数。Nginx处理静态文件效果也很好,那是因为静态文件本身也是磁盘IO操作,处理过程一样。至于说多少万的并发连接,这个毫无意义。我随手写个网络程序都能处理几万的并发,但如果大部分客户端阻塞在那里,就没什么价值。

再看看Apache或者Resin这类应用服务器,之所以称他们为应用服务器,是因为他们真的要跑具体的业务应用,如科学计算、图形图像、数据库读写等。它们很可能是CPU密集型的服务,事件驱动并不合适。例如一个计算耗时2秒,那么这2秒就是完全阻塞的,什么event都没用。想想MySQL如果改成事件驱动会怎么样,一个大型的join或sort就会阻塞住所有客户端。这个时候多进程或线程就体现出优势,每个进程各干各的事,互不阻塞和干扰。当然,现代CPU越来越快,单个计算阻塞的时间可能很小,但只要有阻塞,事件编程就毫无优势。所以进程、线程这类技术,并不会消失,而是与事件机制相辅相成,长期存在。

总结之,事件驱动适合于IO密集型服务,多进程或线程适合于CPU密集型服务,它们各有各的优势,并不存在谁取代谁的倾向。

Apache与Nginx网络模型的更多相关文章

  1. Linux Apache和Nginx网络模型详解

    进程阻塞和挂起的定义: 阻塞是由于进程所需资源得不到满足,并会最终导致进程被挂起     进程挂起的原因并不一定是由于阻塞,也有可能是时间片得不到满足,挂起状态是进程从内存调度到外存中的一种状态,若在 ...

  2. Apache与Nginx的优缺点比较

    1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下ngin ...

  3. Apache与Nginx区别

    1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx ...

  4. 配置apache和nginx的tomcat负载均衡

    概述 本篇文章主要介绍apache和nginx的相关配置,tomcat的相关安装配置我在前面有写过一篇,详细介绍通过两种配置方法配置nginx. tomcat配置参考:http://www.cnblo ...

  5. web服务器选择Apache还是Nginx

    首先我们来谈谈老朋友Apache,Apache HTTP Server(简称Apache)是世界使用排名第一的Web服务器软件,音译为阿帕奇,是Apache软件基金会的一个开放源码Web服务器,可以运 ...

  6. Apache、nginx配置的网站127.0.0.1可以正常访问,内外网的ip地址无法访问,谁的锅?

    最近做开发,发现一个比较尴尬的问题.因为我是一个web开发者,经常要用到Apache或者nginx等服务器软件,经过我测试发现,只要我打开了adsafe,我便不能通过ip地址访问我本地的网站了,比如我 ...

  7. Apache与Nginx对客户端请求的处理机制对比

    Apache与Nginx对客户端请求的处理机制对比 模块 大致为四个模块,核心模块.HTTP模块.邮件模块,以及第三方模块 核心模块主要包含两类功能的支持,一类是主体功能,包括进程管理,权限管理,错误 ...

  8. apache与nginx的虚拟域名配置

    由于开发需求,项目有时候需要设置虚拟域名进行测试.下面是分别是apache和nginx的配置 一.apache 环境:wampserver2.5 1.修改host文件 C:\Windows\Syste ...

  9. (转)apache和nginx的区别

    nginx 相对 apache 的优点: 轻量级,同样起web 服务,比apache 占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下ngin ...

随机推荐

  1. C++中实现链表的删除和颠倒

    MFC工程中关于链表的操作 1.对于给定的整数n,编写算法删除链表中第n个节点,该链表的第一个节点由first指向. 由于C++中没有关于node的标准头文件,要先手动定义node类,此处只定义了简单 ...

  2. chrome 下的 proxy 插件安装

    Install “Proxy SwitchyOmega” extensions for chrome.

  3. hdu5461 Largest Point(沈阳网赛)

    Largest Point Time Limit: 1500/1000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total ...

  4. dom4j和jaxp解析工具的

    dom4j解析中的几个对象 node --branch --document --element --commment --attribute --text branch --document --e ...

  5. 整合Spring.net到asp.net网站开发中初探

    整合Spring.net到asp.net网站开发中初探 http://www.veryhuo.com 2009-10-21 烈火网 投递稿件 我有话说   Spring提供了一个轻量级的用于构建企业级 ...

  6. 队列的实现 -- 数据结构与算法的javascript描述 第五章

    队列也是列表的一种,有不同于列表的规则. 先进先出 入队方法 出队方法 可以找到队首 可以找到队尾 可以查看队列有多长 可以查看队列是否为空 这是一个基本的需求,围绕他来实现,当然我们可以自己扩展列表 ...

  7. Oracle操作数据库oracleHelper

    1 Oracle OracleHelper //============================================================================ ...

  8. Ini文件操作类

    /// <summary> /// Ini文件操作类 /// </summary> public class Ini { // 声明INI文件的写操作函数 WritePriva ...

  9. Hive操作之HQL语句

    HQL操作1.Distribute by    distribute by col按照col列把数据分散到不同的reduce    sort    sort by col 按照col列把数据排序    ...

  10. 这两天写的mybatis配置文件,主要是有输出和输入的存储过程

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-/ ...