死磕nginx系列--nginx入门

nginx 功能介绍

Nginx由于它的稳定性、丰富的模块库、灵活的配置和低系统资源的消耗而闻名.业界一致认为它是Apache2.2+mod_proxy_balancer的轻量级代替者,不只是由于响应静态页面的速度很是快,并且它的模块数量达到Apache的近2/3。对proxy和rewrite模块的支持很完全,还支持mod_fcgi、ssl、vhosts ,适合用来作mongrel clusters的前端HTTP响应。
nginx和Apache同样使用模块化设计,nginx模块包括内置模块和第三方模块,其中内置模块中包含主模块和事件模块。php

nginx处理请求逻辑图
Nginx模块的HTTP请求和响应过程css

nginx能够提供的服务

  1. web 服务.
  2. 负载均衡 (反向代理)
  3. web cache(web 缓存)

nginx 的优势

  1. 高并发。静态小文件
  2. 占用资源少。2万并发、10个线程,内存消耗几百M。
  3. 功能种类比较多。web,cache,proxy。每个功能都不是特别强。
  4. 支持epoll模型,使得nginx能够支持高并发。
  5. nginx 配合动态服务和Apache有区别。(FASTCGI 接口)
  6. 利用nginx能够对IP限速,能够限制链接数。
  7. 配置简单,更灵活。

nginx应用场合

  1. 静态服务器。(图片,视频服务)另外一个lighttpd。并发几万,html,js,css,flv,jpg,gif等。
  2. 动态服务,nginx——fastcgi 的方式运行PHP,jsp。(PHP并发在500-1500,MySQL 并发在300-1500)。
  3. 反向代理,负载均衡。日pv2000W如下,均可以直接用nginx作代理。
  4. 缓存服务。相似 SQUID,VARNISH。

主流web服务产品对比说明

Apache-特性

  1. 2.2版本自己稳定强大,据官方说:其2.4版本性能更强。
  2. prefork模式取消了进程建立开销,性能很高。
  3. 处理动态业务数据时,因关联到后端的引擎和数据库,瓶颈不在与Apache自己。
  4. 高并发时消耗系统资源相对多一些。
  5. 基于传统的select模型。
  6. 扩展库,DSO方法。

nginx-特性

  1. 基于异步IO模型,(epoll,kqueue),性能强,可以支持上万并发。
  2. 对小文件支持很好,性能很高(限静态小文件1M)。
  3. 代码优美,扩展库必须编译进主程序。
  4. 消耗代码资源比较低。
  5. lighttpd(百度贴吧,豆瓣)
  6. 基于异步IO模式,性能和nginx相近。
  7. 扩展库是SO模式,比nginx要灵活。
    8.经过差距(mod_secdownload)可实现文件URL地址加密。

web服务产品性能对比测试

静态数据性能对比
  1. 处理静态文件Apache性能比nginx和lighttpd要差。
  2. nginx在处理小文件优点明显。
  3. 处理静态小文件(小于1M),nginx和lighttpd比Apache更有优点,lighttpd最强。html

    动态数据性能对比
  4. 处理动态内容三者相差不大,主要取决于PHP和数据库的压力。
  5. 当处理动态数据时,三者差距不大,从测试结果看,Apache更有优点一点。这是由于处理动态数据能力取决于PHP和后端数据的提供服务能力。也就是说瓶颈不在web服务器上。
  6. 通常PHP引擎支持的并发参考值300-1000,JAVA引擎并发300-1000,数据库的并发300-1000.前端

为何nginx的整体性能比Apache高。
  1. nginx使用最新的epoll和kqueue网络IO模型,而Apache使用床头的select模式。
  2. 目前Linux下可以承受高并发访问的squid、Memcached 都采用的是epoll网络IO模型。

如何选择WEB服务器:

静态业务:高并发、采用nginx,lighttpd,根据本身的掌握程度或公司的要求。
动态业务:采用nginx和Apache都可。
既有静态业务又有动态业务:nginx或Apache,不要多选要单选。
动态业务能够由前端代理(haproxy),根据页面元素的类型,向后转发相应的服务器进行处理。
思想:咱们工做都不要追求一步到位,知足需求的前提下,先用,而后逐步完善。
提示:nginx作web(Apache,lighttpd)、反向代理(haproxy,lvs,nat)及缓存服务器(squid)也是不错的。
最终建议:对外的业务nginx,对内的业务Apache(yum httpd mysql-server php)。python

nginx实战过程

安装依赖包

  • nginx安装依赖GCC、openssl-devel、pcre-devel和zlib-devel软件库。
  • Pcre全称(Perl Compatible Regular Expressions),中文perl兼容正则表达式,pcre官方站点
yum install  pcre pcre-devel -y 
yum install openssl openssl-devel -y

开始编译

使用./configure --help查看各个模块的使用状况,使用--without-http_ssi_module的方式关闭不须要的模块。可使用--with-http_perl_modules方式安装须要的模块。mysql

编译命令linux

tar -zxf nginx-1.10.1.tar.gz 
cd nginx-1.10.1/
./configure --prefix=/data/app/nginx-1.10.1 --user=nginx --group=nginx  --with-http_ssl_module  --with-http_stub_status_module

useradd nginx -M -s /sbin/nologin 
make && make install 
ln -s /data/app/nginx-1.10.1 /data/app/nginx

测试nginx配置文件是否正常nginx

/data/app/nginx/sbin/nginx -t 
nginx: the configuration file /data/app/nginx-1.10.1/conf/nginx.conf syntax is ok
nginx: configuration file /data/app/nginx-1.10.1/conf/nginx.conf test is successful

启动nginx服务器web

/data/app/nginx/sbin/nginx  -t  ##检查配置文件
/data/app/nginx/sbin/nginx      ##肯定nginx服务
netstat -lntup |grep nginx        ## 检查进程是否正常
curl 192.168.56.12                ## 确认结果

nginx其余命令正则表达式

nginx -s signal
signal:
stop — fast shutdown
quit — graceful shutdown
reload — reloading the configuration file
reopen — reopening the log files
用来打开日志文件,这样nginx会把新日志信息写入这个新的文件中

/data/app/nginx/sbin/nginx -V 查看已经编译的参数。

使用kill命令操做nginx。格式:kill -信号 PID

信号名称

  • TERM,INT 快速关闭
  • QUIT 优雅的关闭,保持吸纳有的客户端链接
  • HUP 重启应用新的配置文件
  • USR1 从新打开日志文件
  • USR2 升级程序
  • WINCH 优雅的关闭工做进程

例子

kill -QUIT  `cat /data/app/nginx/nginx.pid`
kill -HUP `cat /data/app/nginx/nginx.pid`

nginx配置文件

配置基础配置文件

worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
### 测试配置文件是否正常
shell> /data/app/nginx/sbin/nginx -t 
nginx: the configuration file /data/app/nginx-1.10.3/conf/nginx.conf syntax is ok
nginx: configuration file /data/app/nginx-1.10.3/conf/nginx.conf test is successful
shell> curl -I http://192.168.56.12
HTTP/1.1 200 OK

nginx监控

开启nginx的监控服务

开启状态页

#设定查看Nginx状态的地址   
       location /NginxStatus {  
        stub_status on;   
        access_log off;   
        # auth_basic "NginxStatus";   
        # auth_basic_user_file conf/htpasswd;   
       }
  • stub_status on; 表示开启stubStatus的工做状态统计功能。
  • access_log off; 关闭access_log 日志记录功能。
  • auth_basic "NginxStatus"; auth_basic 是nginx的一种认证机制。
  • auth_basic_user_file conf/htpasswd; 用来指定密码文件的位置。

    配置登陆密码

yum install -y httpd-tools
/usr/local/apache/bin/htpasswd -c /data/app/nginx/conf/htpasswd biglittleant 
New password:

完成后会在/data/app/nginx/conf/目录下生成htpasswd文件。

访问URL

# curl http://127.0.0.1/NginxStatus
Active connections: 11921 
server accepts handled requests
 11989 11989 11991 
Reading: 0 Writing: 7 Waiting: 42
  • active connections – 活跃的链接数量
  • server accepts handled requests — 总共处理了11989个链接 , 成功建立11989次握手, 总共处理了11991个请求
  • Reading — 读取客户端的链接数.
  • Writing — 响应数据到客户端的数量
  • Waiting — 开启 keep-alive 的状况下,这个值等于 active – (reading+writing), 意思就是 Nginx 已经处理完正在等候下一次请求指令的驻留链接.

    编写zabbix监控脚本

nginx_status_fun(){
    NGINX_PORT=$1
    NGINX_COMMAND=$2
    nginx_active(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| grep 'Active' | awk '{print $NF}'
        }
    nginx_reading(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| grep 'Reading' | awk '{print $2}'
       }
    nginx_writing(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| grep 'Writing' | awk '{print $4}'
       }
    nginx_waiting(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| grep 'Waiting' | awk '{print $6}'
       }
    nginx_accepts(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| awk NR==3 | awk '{print $1}'
       }
    nginx_handled(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| awk NR==3 | awk '{print $2}'
       }
    nginx_requests(){
        /usr/bin/curl "http://127.0.0.1:"$NGINX_PORT"/NginxStatus/" 2>/dev/null| awk NR==3 | awk '{print $3}'
       }
    case $NGINX_COMMAND in
        active)
            nginx_active;
            ;;
        reading)
            nginx_reading;
            ;;
        writing)
            nginx_writing;
            ;;
        waiting)
            nginx_waiting;
            ;;
        accepts)
            nginx_accepts;
            ;;
        handled)
            nginx_handled;
            ;;
        requests)
            nginx_requests;
        esac 
}

nginx优化

nginx内核优化

net.ipv4.tcp_fin_timeout = 2
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_keepalive_time = 600
net.ipv4.ip_local_port_range = 4000    65000
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.route.gc_timeout = 100
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_synack_retries = 1
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 16384
net.ipv4.tcp_max_orphans = 16384
#如下参数是对iptables防火墙的优化,防火墙不开会提示,能够忽略不理。
net.ipv4.ip_conntrack_max = 25000000
net.ipv4.netfilter.ip_conntrack_max=25000000
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=180
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=60
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait=120

报错汇总

问题1:编译报错

./configure: error: the HTTP rewrite module requires the PCRE library.
You can either disable the module by using —without-http_rewrite_module(伪静态)
option, or install the PCRE library into the system, or build the PCRE library
statically from the source with nginx by using --with-pcre=<path> option
yum install  pcre pcre-devel -y

问题2: 提示找不到libpcre.so.1

解决:

  1. find / -name libpcre.so*
  2. 将找到的路径 追加到 /etc/ld.so.conf
  3. ldconfig 生效。
  4. ln -s /ser/local/lib/libpcre.so.l /lib64
  5. 或编译时指定源码的安装路径:--with-pcre=/data/tools/pcre-8.33
  6. 最终解决方案 yum install pcre-devel -y 不会出现上述报错。

问题3:启动nginx报错

[root@centos6 tools]# /application/nginx/sbin/nginx 
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()

解决办法:(由于开启了Apache服务)

[root@nfs-client application]# lsof -i :80 
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
httpd   35833  www    4u  IPv6 129886      0t0  TCP *:http (LISTEN)
httpd   35834  www    4u  IPv6 129886      0t0  TCP *:http (LISTEN)
httpd   98511 root    4u  IPv6 129886      0t0  TCP *:http (LISTEN)
[root@nfs-client application]# /application/apache/bin/apachectl stop 
[root@nfs-client application]# /application/nginx/sbin/nginx ##从新启动nginx。

扩展阅读:

nginx全局变量

  • $args:这个变量等于请求行中的参数,同$query_string。
  • $is_args: 若是已经设置$args,则该变量的值为"?",不然为""。
  • $content_length: 请求头中的Content-length字段。
  • $content_type: 请求头中的Content-Type字段。
  • $document_uri: 与$uri相同。
  • $document_root: 当前请求在root指令中指定的值。
  • $host: 请求主机头字段,不然为服务器名称。
  • $http_user_agent: 客户端agent信息。
  • $http_cookie: 客户端cookie信息。
  • $limit_rate: 这个变量能够限制链接速率。
  • $request_method: 客户端请求的动做,一般为GET或POST。
  • $remote_addr: 客户端的IP地址。
  • $remote_port: 客户端的端口。
  • $remote_user: 已经通过Auth Basic Module验证的用户名。
  • $request_body_file`: 客户端请求主体的临时文件名。
  • $request_uri: 请求的URI,带参数
  • $request_filename: 当前请求的文件路径,由root或alias指令与URI请求生成。
  • $scheme: 所用的协议,好比http或者是https,好比rewrite ^(.+)$ $scheme://example.com$1 redirect;
  • $server_protocol: 请求使用的协议,一般是HTTP/1.0或HTTP/1.1。
  • $server_addr: 服务器地址,在完成一次系统调用后能够肯定这个值。
  • $server_name: 服务器名称。
  • $server_port: 请求到达服务器的端口号。
  • $request_uri: 包含请求参数的原始URI,不包含主机名,如:/foo/bar.php?arg=baz
  • $uri: 不带请求参数的当前URI,$uri不包含主机名,如/foo/bar.html可能和最初的值有不一样,好比通过重定向之类的。

例子:

访问连接是:http://localhost:88/test1/test2/test.php 
网站路径是:/var/www/html

$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php

nginx plus -- ngx_http_status_module

商业版的 nginx plus 经过他的 ngx_http_status_module 提供了比 nginx 更多的监控指标,能够参看 http://demo.nginx.com/status.html

nginx access log 分析

nginx 的 access log 中能够记录不少有价值的信息,经过分析 access log,能够收集到不少指标。
python 编写的 linux 工具 ngxtop 就实现了对 access log 的分析功能。

web服务器事件处理模型

select

select最先于1983年出如今4.2BSD中,它经过一个select()系统调用来监视多个文件描述符的数组,当select()返回后,该数组中就绪的文件描述符便会被内核修改标志位,使得进程能够得到这些文件描述符从而进行后续的读写操做。
select目前几乎在全部的平台上支持,其良好跨平台支持也是它的一个优势,事实上从如今看来,这也是它所剩很少的优势之一。
select的一个缺点在于单个进程可以监视的文件描述符的数量存在最大限制,在Linux上通常为1024,不过能够经过修改宏定义甚至从新编译内核的方式提高这一限制。
另外,select()所维护的存储大量文件描述符的数据结构,随着文件描述符数量的增大,其复制的开销也线性增加。同时,因为网络响应时间的延迟使得大量TCP链接处于非活跃状态,但调用select()会对全部socket进行一次线性扫描,因此这也浪费了必定的开销。

poll

poll在1986年诞生于System V Release 3,它和select在本质上没有多大差异,可是poll没有最大文件描述符数量的限制。
poll和select一样存在一个缺点就是,包含大量文件描述符的数组被总体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪,它的开销随着文件描述符数量的增长而线性增大。
另外,select()和poll()将就绪的文件描述符告诉进程后,若是进程没有对其进行IO操做,那么下次调用select()和poll()的时候将再次报告这些文件描述符,因此它们通常不会丢失就绪的消息,这种方式称为水平触发(Level Triggered)。

epoll

直到Linux2.6才出现了由内核直接支持的实现方法,那就是epoll,它几乎具有了以前所说的一切优势,被公认为Linux2.6下性能最好的多路I/O就绪通知方法。
epoll能够同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,若是咱们没有采起行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,可是代码实现至关复杂。
epoll一样只告知那些就绪的文件描述符,并且当咱们调用epoll_wait()得到就绪文件描述符时,返回的不是实际的描述符,而是一个表明就绪描述符数量的值,你只须要去epoll指定的一个数组中依次取得相应数量的文件描述符便可,这里也使用了内存映射(mmap)技术,这样便完全省掉了这些文件描述符在系统调用时复制的开销。
另外一个本质的改进在于epoll采用基于事件的就绪通知方式。在select/poll中,进程只有在调用必定的方法后,内核才对全部监视的文件描述符进行扫描,而epoll事先经过epoll_ctl()来注册一个文件描述符,一旦基于某个文件描述符就绪时,内核会采用相似callback的回调机制,迅速激活这个文件描述符,当进程调用epoll_wait()时便获得通知。

nginx -s reload 过程

nginx主进程读取配置文件,若是发现配置文件变动,会建立一个新的主进程,而后同时旧的进程,及旧的子进程关闭,旧进程会拒绝新的链接,服务到本身的链接结束,而后关闭。

Apache select模型和 nginx epoll 模型对比讲解

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(),这时候也不是阻塞的,调用后就等内核发回通知发送的结果就行。整个下来把一个请求分红了不少个阶段,每一个阶段都到不少模块去注册,而后处理,都是异步非阻塞。异步这里指的就是作一个事情,不须要等返回结果,作好了会自动通知你。

select/epoll的特色

select的特色:select 选择句柄的时候,是遍历全部句柄,也就是说句柄有事件响应时,select须要遍历全部句柄才能获取到哪些句柄有事件通知,所以效率是很是低。可是若是链接不多的状况下, select和epoll的LT触发模式相比, 性能上差异不大。
这里要多说一句,select支持的句柄数是有限制的, 同时只支持1024个,这个是句柄集合限制的,若是超过这个限制,极可能致使溢出,并且很是不容易发现问题, 固然能够经过修改linux的socket内核调整这个参数。
epoll的特色:epoll对于句柄事件的选择不是遍历的,是事件响应的,就是句柄上事件来就立刻选择出来,不须要遍历整个句柄链表,所以效率很是高,内核将句柄用红黑树保存的。
对于epoll而言还有ET和LT的区别,LT表示水平触发,ET表示边缘触发,二者在性能以及代码实现上差异也是很是大的。

能够举一个简单的例子来讲明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密集型服务,它们各有各的优点,并不存在谁取代谁的倾向。

相关参考

nginx-日志高级技巧
nginx-官方文档
nginx优化
查看网站排名
nginx-status-demo

相关文章
相关标签/搜索