簡介
Nginx ("engine x") 是一個高性能的HTTP和反向代理伺服器,也是一個IMAP/POP3/SMTP代理伺服器;
作為一款輕量級的Web伺服器,具有占有記憶體少,并發能力強等優勢,是高連接配接并發場景下Apache的不錯的替代品;
本篇主要介紹Nginx作為Web伺服器時,相對于Apache的性能優勢;
下一篇将會介紹Nginx作為方向代理伺服器的實作;
重要特點
非阻塞:資料複制時,磁盤I/O的第一階段是非阻塞的;
事件驅動:通信機制采用epoll模型,支援更大的并發連接配接;
master/worker結構:一個master程序,生成一個或多個worker程序;
基礎架構
<a href="http://s3.51cto.com/wyfs02/M02/25/80/wKioL1NhsRCizui1AAJjCxv__qo087.jpg" target="_blank"></a>
Nginx如何實作高并發:
I/O模型采用異步非阻塞的事件驅動機制,由程序循環處理多個準備好的事件,如epoll機制;
Nginx與Apache對高并發處理上的差別:
對于Apache,每個請求都會獨占一個工作線程,當并發量增大時,也會産生大量的工作線程,導緻記憶體占用急劇上升,同時線程的上下文切換也會導緻CPU開銷增大,導緻在高并發場景下性能下降嚴重;
對于Nginx,一個worker程序隻有一個主線程,通過事件驅動機制,實作循環處理多個準備好的事件,進而實作輕量級和高并發;
部署配置
安裝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<code>yum -y groupinstall “Development tools”</code>
<code>yum -y groupinstall “Server Platform Development”</code>
<code>yum </code><code>install</code> <code>gcc openssl-devel pcre-devel zlib-devel</code>
<code>groupadd -r nginx</code>
<code>useradd</code> <code>-r -g nginx -s </code><code>/sbin/nologin</code> <code>-M nginx</code>
<code>tar</code> <code>xf nginx-1.4.7.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>nginx-1.4.7</code>
<code>mkdir</code> <code>-pv </code><code>/var/tmp/nginx</code>
<code>.</code><code>/configure</code> <code>\</code>
<code> </code><code>--prefix=</code><code>/usr</code> <code>\</code>
<code> </code><code>--sbin-path=</code><code>/usr/sbin/nginx</code> <code>\</code>
<code> </code><code>--conf-path=</code><code>/etc/nginx/nginx</code><code>.conf \</code>
<code> </code><code>--error-log-path=</code><code>/var/log/nginx/error</code><code>.log \</code>
<code> </code><code>--http-log-path=</code><code>/var/log/nginx/access</code><code>.log \</code>
<code> </code><code>--pid-path=</code><code>/var/run/nginx/nginx</code><code>.pid \</code>
<code> </code><code>--lock-path=</code><code>/var/lock/nginx</code><code>.lock \</code>
<code> </code><code>--user=nginx \</code>
<code> </code><code>--group=nginx \</code>
<code> </code><code>--with-http_ssl_module \</code>
<code> </code><code>--with-http_flv_module \</code>
<code> </code><code>--with-http_stub_status_module \</code>
<code> </code><code>--with-http_gzip_static_module \</code>
<code> </code><code>--http-client-body-temp-path=</code><code>/var/tmp/nginx/client/</code> <code>\</code>
<code> </code><code>--http-proxy-temp-path=</code><code>/var/tmp/nginx/proxy/</code> <code>\</code>
<code> </code><code>--http-fastcgi-temp-path=</code><code>/var/tmp/nginx/fcgi/</code> <code>\</code>
<code> </code><code>--http-uwsgi-temp-path=</code><code>/var/tmp/nginx/uwsgi</code> <code>\</code>
<code> </code><code>--http-scgi-temp-path=</code><code>/var/tmp/nginx/scgi</code> <code>\</code>
<code> </code><code>--with-pcre</code>
<code>make</code> <code>&& </code><code>make</code> <code>install</code>
配置
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<code>vi</code> <code>/etc/init</code><code>.d</code><code>/nginx</code> <code># 配置服務腳本</code>
<code>#!/bin/sh</code>
<code>#</code>
<code># nginx - this script starts and stops the nginx daemon</code>
<code># chkconfig: - 85 15</code>
<code># description: Nginx is an HTTP(S) server, HTTP(S) reverse \</code>
<code># proxy and IMAP/POP3 proxy server</code>
<code># processname: nginx</code>
<code># config: /etc/nginx/nginx.conf</code>
<code># config: /etc/sysconfig/nginx</code>
<code># pidfile: /var/run/nginx.pid</code>
<code># Source function library.</code>
<code>. </code><code>/etc/rc</code><code>.d</code><code>/init</code><code>.d</code><code>/functions</code>
<code># Source networking configuration.</code>
<code>. </code><code>/etc/sysconfig/network</code>
<code># Check that networking is up.</code>
<code>[ </code><code>"$NETWORKING"</code> <code>= </code><code>"no"</code> <code>] && </code><code>exit</code> <code>0</code>
<code>nginx=</code><code>"/usr/sbin/nginx"</code>
<code>prog=$(</code><code>basename</code> <code>$nginx)</code>
<code>NGINX_CONF_FILE=</code><code>"/etc/nginx/nginx.conf"</code>
<code>[ -f </code><code>/etc/sysconfig/nginx</code> <code>] && . </code><code>/etc/sysconfig/nginx</code>
<code>lockfile=</code><code>/var/lock/subsys/nginx</code>
<code>make_dirs() {</code>
<code> </code><code># make required directories</code>
<code> </code><code>user=`nginx -V 2>&1 | </code><code>grep</code> <code>"configure arguments:"</code> <code>| </code><code>sed</code> <code>'s/[^*]*--user=\([^ ]*\).*/\1/g'</code> <code>-`</code>
<code> </code><code>options=`$nginx -V 2>&1 | </code><code>grep</code> <code>'configure arguments:'</code><code>`</code>
<code> </code><code>for</code> <code>opt </code><code>in</code> <code>$options; </code><code>do</code>
<code> </code><code>if</code> <code>[ `</code><code>echo</code> <code>$opt | </code><code>grep</code> <code>'.*-temp-path'</code><code>` ]; </code><code>then</code>
<code> </code><code>value=`</code><code>echo</code> <code>$opt | </code><code>cut</code> <code>-d </code><code>"="</code> <code>-f 2`</code>
<code> </code><code>if</code> <code>[ ! -d </code><code>"$value"</code> <code>]; </code><code>then</code>
<code> </code><code># echo "creating" $value</code>
<code> </code><code>mkdir</code> <code>-p $value && </code><code>chown</code> <code>-R $user $value</code>
<code> </code><code>fi</code>
<code> </code><code>fi</code>
<code> </code><code>done</code>
<code>}</code>
<code>start() {</code>
<code> </code><code>[ -x $nginx ] || </code><code>exit</code> <code>5</code>
<code> </code><code>[ -f $NGINX_CONF_FILE ] || </code><code>exit</code> <code>6</code>
<code> </code><code>make_dirs</code>
<code> </code><code>echo</code> <code>-n $</code><code>"Starting $prog: "</code>
<code> </code><code>daemon $nginx -c $NGINX_CONF_FILE</code>
<code> </code><code>retval=$?</code>
<code> </code><code>echo</code>
<code> </code><code>[ $retval -</code><code>eq</code> <code>0 ] && </code><code>touch</code> <code>$lockfile</code>
<code> </code><code>return</code> <code>$retval</code>
<code>stop() {</code>
<code> </code><code>echo</code> <code>-n $</code><code>"Stopping $prog: "</code>
<code> </code><code>killproc $prog -QUIT</code>
<code> </code><code>[ $retval -</code><code>eq</code> <code>0 ] && </code><code>rm</code> <code>-f $lockfile</code>
<code>restart() {</code>
<code> </code><code>configtest || </code><code>return</code> <code>$?</code>
<code> </code><code>stop</code>
<code> </code><code>sleep</code> <code>1</code>
<code> </code><code>start</code>
<code>reload() {</code>
<code> </code><code>echo</code> <code>-n $</code><code>"Reloading $prog: "</code>
<code> </code><code>killproc $nginx -HUP</code>
<code> </code><code>RETVAL=$?</code>
<code>force_reload() {</code>
<code> </code><code>restart</code>
<code>configtest() {</code>
<code> </code><code>$nginx -t -c $NGINX_CONF_FILE</code>
<code>rh_status() {</code>
<code> </code><code>status $prog</code>
<code>rh_status_q() {</code>
<code> </code><code>rh_status ></code><code>/dev/null</code> <code>2>&1</code>
<code>case</code> <code>"$1"</code> <code>in</code>
<code> </code><code>start)</code>
<code> </code><code>rh_status_q && </code><code>exit</code> <code>0</code>
<code> </code><code>$1</code>
<code> </code><code>;;</code>
<code> </code><code>stop)</code>
<code> </code><code>rh_status_q || </code><code>exit</code> <code>0</code>
<code> </code><code>restart|configtest)</code>
<code> </code><code>reload)</code>
<code> </code><code>rh_status_q || </code><code>exit</code> <code>7</code>
<code> </code><code>force-reload)</code>
<code> </code><code>force_reload</code>
<code> </code><code>status)</code>
<code> </code><code>rh_status</code>
<code> </code><code>condrestart|try-restart)</code>
<code> </code><code>;;</code>
<code> </code><code>*)</code>
<code> </code><code>echo</code> <code>$</code><code>"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"</code>
<code> </code><code>exit</code> <code>2</code>
<code>esac</code>
<code>chmod</code> <code>+x </code><code>/etc/init</code><code>.d</code><code>/nginx</code> <code># 複***務腳本執行權限</code>
<code>vi</code> <code>/etc/nginx/nginx</code><code>.conf </code><code># 編輯主配置檔案</code>
<code>worker_processes 2;</code>
<code>error_log </code><code>/var/log/nginx/nginx</code><code>.error.log;</code>
<code>pid </code><code>/var/run/nginx</code><code>.pid;</code>
<code>events {</code>
<code> </code><code>worker_connections 1024;</code>
<code>http {</code>
<code> </code><code>include mime.types;</code>
<code> </code><code>default_type application</code><code>/octet-stream</code><code>;</code>
<code> </code><code>log_format main </code><code>'$remote_addr - $remote_user [$time_local] "$request" '</code>
<code> </code><code>'$status $body_bytes_sent "$http_referer" '</code>
<code> </code><code>'"$http_user_agent" "$http_x_forwarded_for"'</code><code>;</code>
<code> </code><code>sendfile on;</code>
<code> </code><code>keepalive_timeout 65;</code>
<code> </code><code>server {</code>
<code> </code><code>listen 80;</code>
<code> </code><code>server_name xxrenzhe.lnmmp.com;</code>
<code> </code><code>access_log </code><code>/var/log/nginx/nginx</code><code>.access.log main;</code>
<code> </code><code>location / {</code>
<code> </code><code>root </code><code>/www/lnmmp</code><code>.com;</code>
<code> </code><code>index index.php index.html index.htm;</code>
<code> </code><code>}</code>
<code> </code><code>error_page 404 </code><code>/404</code><code>.html;</code>
<code> </code><code>error_page 500 502 503 504 </code><code>/50x</code><code>.html;</code>
<code> </code><code>location = </code><code>/50x</code><code>.html {</code>
<code> </code><code>location ~ \.php$ {</code>
<code> </code><code>root </code><code>/www/lnmmp</code><code>.com;</code>
<code> </code><code>fastcgi_pass 127.0.0.1:9000;</code>
<code> </code><code>fastcgi_index index.php;</code>
<code> </code><code>fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</code>
<code> </code><code>include fastcgi_params;</code>
<code> </code><code>}</code>
<code>vi</code> <code>/etc/nginx/fastcgi_params</code> <code># 編輯fastcgi參數檔案</code>
<code>fastcgi_param GATEWAY_INTERFACE CGI</code><code>/1</code><code>.1;</code>
<code>fastcgi_param SERVER_SOFTWARE nginx;</code>
<code>fastcgi_param QUERY_STRING $query_string;</code>
<code>fastcgi_param REQUEST_METHOD $request_method;</code>
<code>fastcgi_param CONTENT_TYPE $content_type;</code>
<code>fastcgi_param CONTENT_LENGTH $content_length;</code>
<code>fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;</code>
<code>fastcgi_param SCRIPT_NAME $fastcgi_script_name;</code>
<code>fastcgi_param REQUEST_URI $request_uri;</code>
<code>fastcgi_param DOCUMENT_URI $document_uri;</code>
<code>fastcgi_param DOCUMENT_ROOT $document_root;</code>
<code>fastcgi_param SERVER_PROTOCOL $server_protocol;</code>
<code>fastcgi_param REMOTE_ADDR $remote_addr;</code>
<code>fastcgi_param REMOTE_PORT $remote_port;</code>
<code>fastcgi_param SERVER_ADDR $server_addr;</code>
<code>fastcgi_param SERVER_PORT $server_port;</code>
<code>fastcgi_param SERVER_NAME $server_name;</code>
啟動服務
<code>service nginx configtest </code><code># 服務啟動前先驗證配置檔案是否正确</code>
<code>service nginx start</code>
<code>ps</code> <code>-ef |</code><code>grep</code> <code>nginx </code><code># 檢查nginx程序,尤其是worker程序是否與worker_processes值一緻</code>
<code>ss -antupl |</code><code>grep</code> <code>80 </code><code># 檢查服務端口是否啟動</code>
性能測試
測試說明
每次測試都進行3次,最後資料取平均值;
對比測試中的Apache采用event的MPM機制,最大化提高Apache的并發性能;
每次測試後,都需重新啟動服務(httpd或nginx),以防止多次測試資料不準;
測試工具:webbench
優點:比ab能更好的模拟并發請求,最大支援模拟30000并發連接配接;
測試方法
<code># 安裝wenbench</code>
<code>wget http:</code><code>//blog</code><code>.s135.com</code><code>/soft/linux/webbench/webbench-1</code><code>.5.</code><code>tar</code><code>.gz</code>
<code>tar</code> <code>xf webbench-1.5.</code><code>tar</code><code>.gz</code>
<code>cd</code> <code>webbench-1.5</code>
<code># 測試</code>
<code>webbench -c 100 -t 30 http:</code><code>//172</code><code>.16.25.112</code><code>/nginx</code><code>.html </code><code># 測試靜态檔案通路</code>
<code>webbench -c 20 -t 30 http:</code><code>//172</code><code>.16.25.112</code><code>/test_mem</code><code>.php </code><code># 測試動态檔案通路</code>
測試資料
分析趨勢圖
靜态檔案通路趨勢圖
動态檔案通路趨勢圖
總結
綜合上面測試得出的趨勢圖可以看出:
靜态檔案測試時,低并發(200以下)情況下,Nginx和Apach的處理能力相當(2000pages/sec左右),當并發數超過200後,則Apache的處理能力開始下降,而Nginx保持穩定;同時随着并發量的增大,Apache令人诟病的記憶體占用和負載開始急劇上升,與此同時,Nginx在記憶體占用和負載方面的略微提升則可以忽略不計了;
動态檔案測試時,低并發(100以下)情況下,Nginx和Apache的處理能力相當(650pages/sec左右),但Nginx的記憶體占用和負載峰值隻有Apache的50%左右;在高并發情況下(100以上),Apach的動态處理能力開始下滑,當并發達到500時,開始出現失敗的請求,說明此時已達到的Apache的處理上限了,而反觀Nginx,雖然處理動态請求會消耗更多的記憶體,但其處理能力随着并發量的上升而上升,即使并發1000動态請求,也未達到其處理能力上限;
故不管是在靜态檔案請求還是動态檔案請求方面,Nginx的性能都是強勢優于Apache的;雖然可以通過系統調優的方式提高Apache的處理性能,但和Nginx相比,還是不足以打動技術狂熱份子的吧,哈哈!
本文轉自 xxrenzhe11 51CTO部落格,原文連結:http://blog.51cto.com/xxrenzhe/1405272,如需轉載請自行聯系原作者