Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)
一,Nginx基本安全優(yōu)化
1.1 調(diào)整參數(shù)隱藏Nginx軟件版本號(hào)信息
- 一般來(lái)說(shuō),軟件的漏洞都和版本有關(guān),這個(gè)很像汽車的缺陷,同一批次的要有問(wèn)題就都有問(wèn)題,別的批次可能就都是好的。因此,我們應(yīng)盡量隱藏或消除Web服務(wù)對(duì)訪問(wèn)用戶顯示各類敏感信息(例如Web軟件名稱及版本號(hào)等信息),這樣惡意的用戶就很難猜到他攻擊的服務(wù)器所用的是否有特定漏洞的軟件,或者是否有對(duì)應(yīng)漏洞的某一特定版本,從而加強(qiáng)Web服務(wù)的安全性。這在武俠小說(shuō)里,就相當(dāng)于隱身術(shù),你隱身了,對(duì)手就很難打著你了。
- 想要隱身,首先要了解所使用軟件的版本號(hào),對(duì)于Linux客戶端,可通過(guò)命令行查看Nginx版本號(hào),最簡(jiǎn)單的方法就是在Linux客戶端系統(tǒng)命令行執(zhí)行如下curl命令:
在Windows客戶端上,通過(guò)瀏覽器訪問(wèn)Web服務(wù)時(shí),若找不到頁(yè)面,默認(rèn)報(bào)錯(cuò)的信息如下圖所示:
以上雖然是不同的客戶端,但是都獲得了Nginx軟件名稱,而且查到了Nginx的版本號(hào),這就使得Nginx Web服務(wù)的安全存在一定的風(fēng)險(xiǎn),因此,應(yīng)隱藏掉這些敏感信息或用一個(gè)其他的名字將其替代。例如,下面是百度搜索引擎網(wǎng)站W(wǎng)eb軟件的更名做法:
[root@LNMP html]# curl -I baidu.com HTTP/1.1 200 OK Date: Fri, 25 Aug 2017 12:22:29 GMT Server: Apache #將Web服務(wù)軟件更名為了Apache,并且版本號(hào)也去掉了 [root@LNMP html]# curl -I -s www.baidu.com HTTP/1.1 200 OK Server: bfe/1.0.8.18 #將Web服務(wù)軟件更名為了bfe,并且版本號(hào)改為1.0.8.18(閉源軟件名稱和版本就無(wú)所謂了)門(mén)戶網(wǎng)站尚且如此,我們也學(xué)著隱藏或改掉應(yīng)用服務(wù)軟件名和版本號(hào)把!事實(shí)上,還可以通過(guò)配置文件加參數(shù)來(lái)隱藏Nginx版本號(hào)。編輯nginx.conf配置文件增加參數(shù),實(shí)現(xiàn)隱藏Nginx版本號(hào)的方式如下:
#在Nginx配置文件nginx.conf中的http標(biāo)簽段內(nèi)加入“server_tokens off”http { ............... server_tokens off; ............... }此參數(shù)放置在http標(biāo)簽內(nèi),作用是控制http response header內(nèi)的Web服務(wù)版本信息的顯示,以及錯(cuò)誤信息中Web服務(wù)版本信息的顯示。
server_tokens參數(shù)的官方說(shuō)明如下: syntax: server_tokens on|off; default: server_tokens on; context: http,server,location官方資料地址:http://nginx.org/en/docs/http/ngx_http_core_module.html
配置完畢后保存,重新加載配置文件,再次通過(guò)curl查看,結(jié)果如下:
[root@LNMP nginx]# curl -I 192.168.0.220 HTTP/1.1 200 OK Server: nginx #版本號(hào)已經(jīng)消失 Date: Wed, 23 Aug 2017 11:22:15 GMT Content-Type: text/html; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP/5.3.28 Link: <http://192.168.0.220/wp-json/>; rel="https://api.w.org/"此時(shí),瀏覽器的報(bào)錯(cuò)提示中沒(méi)有了版本號(hào),如下圖所示,修改成功。
1.2 更改源碼隱藏Nginx軟件名及版本號(hào)
隱藏了Nginx版本號(hào)后,更進(jìn)一步,可以通過(guò)一些手段把Web服務(wù)軟件的名稱也隱藏起來(lái),或者更改為其他Web服務(wù)軟件名以迷惑黑客。但軟件名字的隱藏修改,一般情況下不會(huì)有配置參數(shù)和入口,Nginx也不例外,這可能是由于商業(yè)及品牌展示等原因,軟件提供商不希望使用者把軟件名字隱藏起來(lái)。因此,此處需要更改Nginx源代碼,具體的解決方法如下:
1.2.1 第一步:依次修改3個(gè)Nginx源碼文件。
修改的第一個(gè)文件為nginx-1.6.3/src/core/nginx.h,如下:
[root@LNMP ~]# cd /usr/src/nginx-1.6.2/src/core/ [root@LNMP core]# ls -l nginx.h -rw-r--r--. 1 1001 1001 351 Sep 16 2014 nginx.h [root@LNMP core]# sed -n '13,17p' nginx.h define NGINX_VERSION "1.6.2" #修改為想要顯示的版本號(hào) define NGINX_VER "nginx/" NGINX_VERSION 將nginx修改為想要修改的軟件名稱。 define NGINX_VAR "NGINX" #將nginx修改為想要修改的軟件名稱 define NGX_OLDPID_EXT ".oldbin"修改后的結(jié)果如下:
[root@LNMP core]# sed -n '13,17p' nginx.h define NGINX_VERSION "0.0.0.0" define NGINX_VER "yunjisuan/" NGINX_VERSION define NGINX_VAR "YUNJISUAN" define NGX_OLDPID_EXT ".oldbin"修改的第二個(gè)文件是nginx-1.6.3/src/http/ngx_http_header_filter_module.c的第49行,需要修改的字符串內(nèi)容如下:
ls -l /usr/src/nginx-1.6.2/src/http/ngx_http_header_filter_module.c -rw-r--r--. 1 1001 1001 19321 Sep 16 2014 /usr/src/nginx-1.6.2/src/http/ngx_http_header_filter_module.c [root@LNMP http]# grep -n 'Server: nginx' ngx_http_header_filter_module.c 49:static char ngx_http_server_string[] = "Server: nginx" CRLF; #修改本行結(jié)尾的nginx通過(guò)sed替換修改,后如下:
[] 49:static char ngx_http_server_string[] = "Server: nginx" CRLF; [] [] 49:static char ngx_http_server_string[] = "Server: yunjisuan" CRLF;修改的第三個(gè)文件是nginx-1.6.3/src/http/nginx_http_special_response.c,對(duì)面頁(yè)面報(bào)錯(cuò)時(shí),它會(huì)控制是否展開(kāi)敏感信息。這里輸出修改前的信息ngx_http_special_response.c中的第21~30行,如下:
[] static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER "</center>" CRLF "</body>" CRLF "</html>" CRLF ;static u_char ngx_http_error_tail[] = "<hr><center>nginx</center>" CRLF "</body>" CRLF修改后的結(jié)果如下:
[] static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER " (Mr.chen 2018-08-26)</center>" CRLF "</body>" CRLF "</html>" CRLF ;static u_char ngx_http_error_tail[] = "<hr><center>yunjisuan</center>" CRLF "</body>" CRLF "</html>" CRLF ;1.2.2 第二步是修改后編輯軟件,使其生效
修改后再編譯安裝軟件,如果是已經(jīng)安裝好的服務(wù),需要重新編譯Nginx,配好配置,啟動(dòng)服務(wù)。
再次使瀏覽器出現(xiàn)404錯(cuò)誤,然后看訪問(wèn)結(jié)果,如下圖所示:
如上面所示:Nginx的軟件和版本名都被改掉了,并且加上了本人的大名。
再看看Linux curl命令響應(yīng)頭部信息,如下:
1.3 更改Nginx服務(wù)的默認(rèn)用戶
- 為了讓W(xué)eb服務(wù)更安全,要盡可能地改掉軟件默認(rèn)的所有配置,包括端口,用戶等。
- 下面就來(lái)更改Nginx服務(wù)的默認(rèn)用戶
- 首先,查看Nginx服務(wù)對(duì)應(yīng)的默認(rèn)用戶。一般情況下,Nginx服務(wù)啟動(dòng)后,默認(rèn)使用的用戶是nobody,查看默認(rèn)的配置文件,如下:
為了防止黑客猜到這個(gè)Web服務(wù)的用戶,我們需要更改成特殊的用戶名,例如nginx或特殊點(diǎn)的inca,但是這個(gè)用戶必須是系統(tǒng)里事先存在的,下面以nginx用戶為例進(jìn)行說(shuō)明。
(1)為Nginx服務(wù)建立新用戶
useradd nginx -s /sbin/nologin -M #不需要有系統(tǒng)登錄權(quán)限,應(yīng)當(dāng)禁止登陸。(2)配置Nginx服務(wù),讓其使用剛建立的nginx用戶
更改Nginx服務(wù)默認(rèn)使用用戶,方法有二:
第一種:直接更改配置文件參數(shù),將默認(rèn)的#user nobody;改為如下內(nèi)容:
user nginx nginx;
如果注釋或不設(shè)置上述參數(shù),默認(rèn)為nobody用戶,不推薦使用nobody用戶名,最好采用一個(gè)普通用戶,此處用大家習(xí)慣的,前面建立好的nginx用戶。
第二種:直接在編譯nginx軟件時(shí)指定編譯的用戶和組,命令如下:
./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module(3)檢查更改用戶的效果
重新加載配置后,檢查Nginx服務(wù)進(jìn)程的對(duì)應(yīng)用戶,如下:
[root@LNMP conf]# ps -ef | grep nginx | grep -v grep root 52023 1 0 11:30 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 52024 52023 0 11:30 ? 00:00:00 nginx: worker process通過(guò)查看上述更改后的Nginx進(jìn)程,可以看到worker processes進(jìn)程對(duì)應(yīng)的用戶都變成了nginx。所以,我們有理由得出結(jié)論,上述的兩種方法都可設(shè)置Nginx的worker進(jìn)程運(yùn)行的用戶。當(dāng)然,Nginx的主進(jìn)程還是以root身份運(yùn)行的。
二,根據(jù)參數(shù)優(yōu)化Nginx服務(wù)性能
2.1 優(yōu)化Nginx服務(wù)的worker進(jìn)程個(gè)數(shù)
- 在高并發(fā),高訪問(wèn)量的Web服務(wù)場(chǎng)景,需要事先啟動(dòng)好更多的Nginx進(jìn)程,以保證快速響應(yīng)并處理大量并發(fā)用戶的請(qǐng)求。
- 這類似于開(kāi)飯店,在營(yíng)業(yè)前,需要事先招聘一定數(shù)量的服務(wù)員準(zhǔn)備接待顧客,但這里就有一個(gè)問(wèn)題,如果飯店對(duì)客流沒(méi)有正確預(yù)估,就會(huì)導(dǎo)致一些問(wèn)題發(fā)生,例如:服務(wù)員人數(shù)招聘多了,但是客流很少,那么服務(wù)員就可能很閑,沒(méi)事干,飯店的成本也高了;如果客流很大,而服務(wù)員人數(shù)少了,可能就接待不過(guò)來(lái)顧客,導(dǎo)致顧客吃飯?bào)w驗(yàn)差。因此,飯店要根據(jù)客戶的流量及并發(fā)量來(lái)調(diào)整接待的服務(wù)人員數(shù)量,然后根據(jù)檢測(cè)顧客量變化及時(shí)調(diào)整到最佳配置。
- Nginx服務(wù)就相當(dāng)于飯店,網(wǎng)站用戶就相當(dāng)于顧客,Nginx的進(jìn)程就相當(dāng)于服務(wù)員,下面就來(lái)優(yōu)化Nginx進(jìn)程的個(gè)數(shù)。
2.1.1 優(yōu)化Nginx進(jìn)程對(duì)應(yīng)的配置
#優(yōu)化Nginx進(jìn)程對(duì)應(yīng)Nginx服務(wù)的配置參數(shù)如下: worker_processes 1; #指定了Nginx要開(kāi)啟的進(jìn)程數(shù),結(jié)尾數(shù)字就是進(jìn)程個(gè)數(shù)上述參數(shù)調(diào)整的是Nginx服務(wù)的worker進(jìn)程數(shù),Nginx有Master進(jìn)程和worker進(jìn)程之分,Master為管理進(jìn)程,真正接待“顧客”的是worker進(jìn)程。
2.1.2 優(yōu)化Nginx進(jìn)程個(gè)數(shù)的策略
- 前面已經(jīng)講解過(guò),worker_processes參數(shù)大小的設(shè)置最好和網(wǎng)站的用戶數(shù)量相關(guān)聯(lián),可如果是新配置,不知道網(wǎng)站的用戶數(shù)量該怎么辦呢?
- 搭建服務(wù)器時(shí),worker進(jìn)程數(shù)最開(kāi)始的設(shè)置可以等于CPU的核數(shù),且worker進(jìn)程數(shù)要多一些,這樣起始提供服務(wù)時(shí)就不會(huì)出現(xiàn)因?yàn)樵L問(wèn)量快速增加而臨時(shí)啟動(dòng)新進(jìn)程提供服務(wù)的問(wèn)題,縮短了系統(tǒng)的瞬時(shí)開(kāi)銷和提供服務(wù)的時(shí)間,提升了服務(wù)用戶的速度。高流量高并發(fā)場(chǎng)合也可以考慮將進(jìn)程數(shù)提高至CPU核數(shù)*2,具體情況要根據(jù)實(shí)際的業(yè)務(wù)來(lái)選擇,因?yàn)檫@個(gè)參數(shù)除了要和CPU核數(shù)匹配外,也和硬盤(pán)存儲(chǔ)的數(shù)據(jù)及系統(tǒng)的負(fù)載有關(guān),設(shè)置為CPU的核數(shù)是一個(gè)好的起始配置,這也是官方的建議。
2.1.3 查看Web服務(wù)器CPU硬件資源信息
下面介紹查看Linux服務(wù)器CPU總核數(shù)的方法:
(1)通過(guò)/proc/cpuinfo可查看CPU個(gè)數(shù)及總核數(shù)。查看CPU總核數(shù)的示例如下:
[root@LNMP ~] processor : 0 processor : 1 processor : 2 processor : 3 [root@LNMP ~] 4 [root@LNMP ~] 4 [root@LNMP ~] physical id : 0 physical id : 0 physical id : 0 physical id : 0 [root@LNMP ~] 1(2)通過(guò)執(zhí)行top命令,然后按數(shù)字1,即可顯示所有的CPU核數(shù),如下:
2.1.4 實(shí)踐修改Nginx配置
假設(shè)服務(wù)器的CPU顆數(shù)為1顆,核數(shù)為4核,則初始的配置可通過(guò)查看默認(rèn)的nginx.conf里的worker_processes數(shù)來(lái)了解,命令如下:
[root@LNMP ~]# grep worker_processes /usr/local/nginx/conf/nginx.conf worker_processes 1; [root@LNMP ~]# sed -i 's#worker_processes 1#worker_processes 4#' /usr/local/nginx/conf/nginx.conf [root@LNMP ~]# grep worker_processes /usr/local/nginx/conf/nginx.conf worker_processes 4; #提示可以通過(guò)vi修改#優(yōu)雅重啟Nginx,使修改生效,如下: [root@LNMP ~]# /usr/local/nginx/sbin/nginx -t nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful [root@LNMP ~]# /usr/local/nginx/sbin/nginx -s reload#現(xiàn)在檢查修改后的worker進(jìn)程數(shù)量,如下: [root@LNMP ~]# ps -ef | grep "nginx" | grep -v grep root 1110 1 0 11:12 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 1429 1110 0 11:33 ? 00:00:00 nginx: worker process nginx 1430 1110 0 11:33 ? 00:00:00 nginx: worker process nginx 1431 1110 0 11:33 ? 00:00:00 nginx: worker process nginx 1432 1110 0 11:33 ? 00:00:00 nginx: worker process從“worker_processes 4”可知,worker進(jìn)程數(shù)為4個(gè)。Nginx Master主進(jìn)程不包含在這個(gè)參數(shù)內(nèi),Nginx Master的主進(jìn)程為管理進(jìn)程,負(fù)責(zé)調(diào)度和管理worker進(jìn)程。
有關(guān)worker_processes參數(shù)的官方說(shuō)明如下:
syntax: worker_processes number; #此行為參數(shù)語(yǔ)法,number為數(shù)量 default: worker_processes 1; #此行意思是不匹配該參數(shù),軟件默認(rèn)情況數(shù)量為1 context: main; #此行為worker_processes參數(shù)可以放置的位置worker_processes為定義worker進(jìn)程數(shù)的數(shù)量,建議設(shè)置為CPU的核數(shù)或CPU核數(shù)*2,具體情況要根據(jù)實(shí)際的業(yè)務(wù)來(lái)選擇,因?yàn)檫@個(gè)參數(shù),除了要和CPU核數(shù)匹配外,和硬盤(pán)存儲(chǔ)的數(shù)據(jù)以系統(tǒng)的負(fù)載也有關(guān),設(shè)置為CPU的個(gè)數(shù)或核數(shù)是一個(gè)好的起始配置。From:http://nginx.org/en/docs/ngx_core_module.html
2.2 優(yōu)化綁定不同的Nginx進(jìn)程到不同的CPU上
- 默認(rèn)情況下,Nginx的多個(gè)進(jìn)程有可能跑在某一個(gè)CPU或CPU的某一核上,導(dǎo)致Nginx進(jìn)程使用硬件的資源不均,本節(jié)的優(yōu)化是盡可能地分配不同的Nginx進(jìn)程給不同的CPU處理,達(dá)到充分有效利用硬件的多CPU多核資源的目的。
- 在優(yōu)化不同的Nginx進(jìn)程對(duì)應(yīng)不同的CPU配置時(shí),四核CPU服務(wù)器的參數(shù)配置參考如下:
四核和八核CPU服務(wù)器的參數(shù)配置參考如下:
八核掩碼 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000; 四核掩碼 worker_cpu_affinity 0001 0010 0100 1000;worker_cpu_affinity 的作用是綁定不同的worker進(jìn)程數(shù)到一組CPU上。通過(guò)設(shè)置bitmask控制進(jìn)程允許使用的CPU,默認(rèn)worker進(jìn)程不會(huì)綁定到任何CPU(自動(dòng)平均分配。)
2.2.1 實(shí)驗(yàn)環(huán)境準(zhǔn)備
| Nginx | 192.168.0.220 | nginxWeb |
| 測(cè)試機(jī)1 | 192.168.0.240 | Webbench壓力測(cè)試 |
| 測(cè)試機(jī)2 | 192.168.0.245 | Webbench壓力測(cè)試 |
虛擬機(jī)開(kāi)啟4核心
2.2.2 第一步:不綁定worker進(jìn)程進(jìn)行壓力測(cè)試
#配置文件如下:(未綁定worker進(jìn)程) [root@LNMP nginx]# cat conf/nginx.conf worker_processes 4; #worker_cpu_affinity 0001 0010 0100 1000; events {worker_connections 10240; } http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 80;server_name bbs.yunjisuan.com;location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }#在NginxWeb上執(zhí)行如下命令: [root@LNMP nginx]# top -u nginx Tasks: 120 total, 1 running, 119 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.2%sy, 0.0%ni, 99.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1004412k total, 911632k used, 92780k free, 6952k buffers Swap: 2031608k total, 0k used, 2031608k free, 749976k cachedPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1454 nginx 20 0 49240 5640 468 S 0.0 0.6 0:00.00 nginx 1455 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx 1456 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx 1457 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx #在以上界面時(shí)按鍵盤(pán)的數(shù)值1鍵,出現(xiàn)如下界面: top - 14:44:46 up 36 min, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 120 total, 1 running, 119 sleeping, 0 stopped, 0 zombie Cpu0 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu1 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu2 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu3 : 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1004412k total, 911384k used, 93028k free, 6960k buffers Swap: 2031608k total, 0k used, 2031608k free, 749976k cachedPID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1454 nginx 20 0 49240 5640 468 S 0.0 0.6 0:00.00 nginx 1455 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx 1456 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx 1457 nginx 20 0 49240 5672 500 S 0.0 0.6 0:00.00 nginx在另外的兩臺(tái)測(cè)試機(jī)器上同時(shí)進(jìn)行壓力測(cè)試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/
結(jié)果如下:
2.2.3 第二步:綁定worker進(jìn)程進(jìn)行壓力測(cè)試
#配置文件如下(綁定worker進(jìn)程) [root@LNMP nginx]# cat conf/nginx.conf worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; #修改本行 events {worker_connections 1024; } http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 80;server_name bbs.yunjisuan.com;location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }在另外的兩臺(tái)測(cè)試機(jī)器上同時(shí)進(jìn)行壓力測(cè)試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/
結(jié)果如下:
根據(jù)圖示,我們基本可以看出,平均綁定worker進(jìn)程和不綁定的實(shí)驗(yàn)效果基本是一致的(CPU0是默認(rèn)會(huì)被使用的)。原因在nginx在經(jīng)過(guò)不斷的優(yōu)化后,會(huì)自動(dòng)對(duì)worker進(jìn)程進(jìn)行動(dòng)態(tài)的平均分配。
2.2.4 第三步:修改nginx配置,將所有worker進(jìn)程綁定到CPU3上
#配置文件如下所示: [root@LNMP nginx]# cat conf/nginx.conf worker_processes 4; worker_cpu_affinity 1000 1000 1000 1000; #修改本行 events {worker_connections 1024; } http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 80;server_name bbs.yunjisuan.com;location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }在另外的兩臺(tái)測(cè)試機(jī)器上同時(shí)進(jìn)行壓力測(cè)試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/
結(jié)果如下:
從上圖我們可以得知,worker進(jìn)程的壓力被集中分配到了CPU3上。(CPU0是默認(rèn)被使用的)
2.3 Nginx事件處理模型優(yōu)化
- Nginx的連接處理機(jī)制在不同的操作系統(tǒng)會(huì)采用不同的額I/O模型,在Linux下,Nginx使用epoll的I/O多路復(fù)用模型,在Freebsd中使用kqueue的I/O多路復(fù)用模型,在Solaris中使用/dev/poll方式的I/O多路復(fù)用模型,在Windows中使用的是icop,等等。
- 要根據(jù)系統(tǒng)類型選擇不同的事件處理模型,可供使用的選擇有“use [kqueue|rtsig|epoll|/dev/poll|select|poll];”。因?yàn)榻虒W(xué)使用的是CentOS 6.5 Linux,因此將Nginx的事件處理模型調(diào)整為epoll模型。
根據(jù)Nginx官方文檔建議,也可以不指定事件處理模型,Nginx會(huì)自動(dòng)選擇最佳的事件處理模型服務(wù)。
對(duì)于使用連接進(jìn)程的方法,通常不需要進(jìn)行任何設(shè)置,Nginx會(huì)自動(dòng)選擇最有效辦法。
2.4 調(diào)整Nginx單個(gè)進(jìn)程允許的客戶端最大連接數(shù)
接下來(lái),調(diào)整Nginx單個(gè)進(jìn)程允許的客戶端最大連接數(shù),這個(gè)控制連接數(shù)的參數(shù)為work_connections。
worker_connections的值要根據(jù)具體服務(wù)器性能和程序的內(nèi)存使用量來(lái)指定(一個(gè)進(jìn)程啟動(dòng)使用的內(nèi)存根據(jù)程序確定),如下:
下面是worker_connections的官方說(shuō)明
參數(shù)語(yǔ)法:worker_connections number
默認(rèn)配置:worker_connections 512
放置位置:events
說(shuō)明:
worker_connections用來(lái)設(shè)置一個(gè)worker process支持的最大并發(fā)連接數(shù),這個(gè)連接數(shù)包括了所有鏈接,例如:代理服務(wù)器的連接,客戶端的連接等,實(shí)際的并發(fā)連接數(shù)除了受worker_connections參數(shù)控制外,還和最大打開(kāi)文件數(shù)worker_rlimit_nofile有關(guān)(見(jiàn)下文),Nginx總并發(fā)連接=worker數(shù)量*worker_connections。
參考資料:http://nginx.org/en/docs/ngx_core_module.html
2.5 配置Nginx worker進(jìn)程最大打開(kāi)文件數(shù)
接下來(lái),調(diào)整配置Nginx worker進(jìn)程的最大打開(kāi)文件數(shù),這個(gè)控制連接數(shù)的參數(shù)為worker_rlimit_nofile。該參數(shù)的實(shí)際配置如下:
worker_rlimit_nofile 65535; 最大打開(kāi)文件數(shù),可設(shè)置為系統(tǒng)優(yōu)化后的ulimit -HSn的結(jié)果下面是worker_rlimit_nofile number的官方說(shuō)明:
參數(shù)語(yǔ)法:worker_rlimit_nofile number
默認(rèn)配置:無(wú)
放置位置:主標(biāo)簽段
說(shuō)明:此參數(shù)的作用是改變worker processes能打開(kāi)的最大文件數(shù)
參考資料:http://nginx.org/en/docs/ngx_core_module.html
備注:
Linux系統(tǒng)文件最大打開(kāi)數(shù)設(shè)置:ulimit -n 65535
2.5.1 實(shí)驗(yàn)環(huán)境準(zhǔn)備
| Nginx | 192.168.0.220 | nginxWeb |
| 測(cè)試機(jī)1 | 192.168.0.240 | Webbench壓力測(cè)試 |
| 測(cè)試機(jī)2 | 192.168.0.245 | Webbench壓力測(cè)試 |
2.5.2 修改nginx.conf配置文件
[root@LNMP nginx]# cat conf/nginx.conf worker_processes 1; #worker_cpu_affinity 0000 0010 0100 1000; #worker_rlimit_nofile 65535; events {worker_connections 1024; } http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 80;server_name bbs.yunjisuan.com;location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }先定1核1024連接數(shù)。同學(xué)們注意多開(kāi)幾個(gè)虛擬機(jī)進(jìn)行壓力測(cè)試。不然的話,web服務(wù)器還沒(méi)出問(wèn)題,你測(cè)試服務(wù)器先down掉了。
2.5.2 測(cè)試nginx服務(wù)連接數(shù)的極值
#使用這個(gè)命令可以抓取nginx的連接數(shù) [root@LNMP nginx]# netstat -antp | grep nginx | wc -l 554 [root@LNMP nginx]# netstat -antp | grep nginx | wc -l 471逐漸提高壓力,抓連接數(shù),看看nginx啥時(shí)候down
2.6 開(kāi)啟高效文件傳輸模式
(1)設(shè)置參數(shù):sendfile on;
sendfile參數(shù)用于開(kāi)啟文件的高效傳輸模式。同時(shí)將tcp_nopush和tcp_nodelay兩個(gè)指令設(shè)置為on,可防止網(wǎng)絡(luò)及磁盤(pán)I/O阻塞,提升Nginx工作效率。
syntax: sendfile on | off; default: sendfile off; context: http,server,location,if in location參數(shù)作用:
激活或禁用sendfile()功能功能。sendfile()是作用于兩個(gè)文件描述符之間的數(shù)據(jù)拷貝函數(shù),這個(gè)拷貝操作是在內(nèi)核之中的,被稱為“零拷貝”,sendfile()比read和write函數(shù)要高效很多,因?yàn)?#xff0c;read和write函數(shù)要把數(shù)據(jù)拷貝到應(yīng)用層再進(jìn)行操作。相關(guān)控制參數(shù)還有sendfile_max_chunk,同學(xué)們可以執(zhí)行查詢。細(xì)節(jié)見(jiàn)http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile
(2)設(shè)置參數(shù):tcp_nopush on;
syntax: tcp_nopush on | off; default: tcp_nopush off; context: http,server,location參數(shù)作用:
激活或禁用Linux上的TCP_CORK socket選項(xiàng),此選項(xiàng)僅僅當(dāng)開(kāi)啟sendfile時(shí)才生效,激活這個(gè)tcp_nopush參數(shù)可以允許把http response header和文件的開(kāi)始部分放在一個(gè)文件里發(fā)布,其積極的作用是減少網(wǎng)絡(luò)報(bào)文段的數(shù)量。細(xì)節(jié)見(jiàn)http://nginx.org/en/docs/http/ngx_http_core_module.html。
2.7 優(yōu)化Nginx連接參數(shù),調(diào)整連接超時(shí)時(shí)間
2.7.1 什么是連接超時(shí)
- 先來(lái)個(gè)比喻吧,某飯店請(qǐng)了服務(wù)員招待顧客,但是現(xiàn)在飯店不景氣,此時(shí),為多余的服務(wù)員發(fā)工資使得成本被提高,想減少飯店開(kāi)支成本就得解雇服務(wù)員。
- 這里的服務(wù)員就相當(dāng)于Nginx服務(wù)建立的連接,當(dāng)服務(wù)器建立的連接沒(méi)有接收處理請(qǐng)求時(shí),可在指定的時(shí)間內(nèi)就讓它超時(shí)自動(dòng)退出。還有當(dāng)Nginx和FastCGI服務(wù)建立連接請(qǐng)求PHP時(shí),如果因?yàn)橐恍┰?#xff08;負(fù)載高,停止響應(yīng)),FastCGI服務(wù)無(wú)法給Nginx返回?cái)?shù)據(jù),此時(shí)可以通過(guò)配置Nginx服務(wù)參數(shù)使其不會(huì)死等,因?yàn)榍懊嬗眠^(guò)戶還等著它返回?cái)?shù)據(jù)呢,例如,可設(shè)置為如果請(qǐng)求FastCGI 10秒內(nèi)不能返回?cái)?shù)據(jù),那么Nginx就中斷本次請(qǐng)求,向用戶匯報(bào)取不到數(shù)據(jù)的錯(cuò)誤。
2.7.2 連接超時(shí)的作用
- 將無(wú)用的連接設(shè)置為盡快超時(shí),可以保護(hù)服務(wù)器的系統(tǒng)資源(CPU,內(nèi)存,磁盤(pán))。
- 當(dāng)連接很多時(shí),及時(shí)斷掉那些已經(jīng)建立好的但又長(zhǎng)時(shí)間不做事的連接,以減少其占用的服務(wù)器資源,因?yàn)榉?wù)器維護(hù)連接也是消耗資源的。
- 有時(shí)黑客或惡意用戶攻擊網(wǎng)站,就會(huì)不斷地和服務(wù)器建立多個(gè)連接,消耗連接數(shù),但是啥也不干,大量消耗服務(wù)器的資源,此時(shí)就應(yīng)該及時(shí)斷掉這些惡意占用資源的連接。
- LNMP環(huán)境中,如果用戶請(qǐng)求了動(dòng)態(tài)服務(wù),則Nginx就會(huì)建立連接,請(qǐng)求FastCGI服務(wù)以及后端MySQL服務(wù),此時(shí)這個(gè)Nginx連接就要設(shè)定一個(gè)超時(shí)時(shí)間,在用戶容忍的時(shí)間內(nèi)返回?cái)?shù)據(jù),或者再多等一會(huì)兒后端服務(wù)返回?cái)?shù)據(jù),具體的策略要根據(jù)具體業(yè)務(wù)進(jìn)行具體分析。當(dāng)然了,后端的FastCGI服務(wù)及MySQL服務(wù)也有對(duì)連接的超時(shí)控制。
簡(jiǎn)單的說(shuō),連接超時(shí)是服務(wù)的一種自我管理,自我保護(hù)的重要機(jī)制。
2.7.3 連接超時(shí)帶來(lái)的問(wèn)題,以及不同程序連接設(shè)定知識(shí)
- 服務(wù)器建立新連接也是要消耗資源的,因此,超時(shí)設(shè)置得太短而并發(fā)很大,就會(huì)導(dǎo)致服務(wù)器瞬間無(wú)法響應(yīng)用戶的請(qǐng)求,導(dǎo)致用戶體驗(yàn)下降。
- 企業(yè)生產(chǎn)有些PHP程序站點(diǎn)會(huì)希望設(shè)置成短連接,因?yàn)镻HP程序建立連接消耗的資源和時(shí)間相對(duì)要少些。而對(duì)于Java程序站點(diǎn)來(lái)說(shuō),一般建議設(shè)置長(zhǎng)連接,因?yàn)镴ava程序建立連接消耗的資源和時(shí)間更多,這是語(yǔ)言運(yùn)行機(jī)制決定的。
2.7.4 Nginx連接超時(shí)的參數(shù)設(shè)置
(1)設(shè)置參數(shù):keepalive_timeout 60;
用于設(shè)置客戶端連接保持會(huì)話的超時(shí)時(shí)間為60秒。超過(guò)這個(gè)時(shí)間,服務(wù)器會(huì)關(guān)閉該連接,此數(shù)值為參考值。
keepalive_timeout參數(shù)的官方說(shuō)明如下: syntax: keepalive_timeout timeout [header_timeout] #參數(shù)語(yǔ)法 default: keepalive_timeout 75s; #參數(shù)默認(rèn)大小 context: http,serverr,location #可以放置的標(biāo)簽段參數(shù)作用:
- keep-alive可以使客戶端到服務(wù)器端已經(jīng)建立的連接一直工作不退出,當(dāng)服務(wù)器有持續(xù)請(qǐng)求時(shí),keep-alive會(huì)使用已經(jīng)建立的連接提供服務(wù),從而避免服務(wù)器重新建立新連接處理請(qǐng)求。
- 此參數(shù)設(shè)置一個(gè)keep-alive(客戶端連接在服務(wù)器端保持多久后退出),其單位是秒,和HTTP響應(yīng)header域的“Keep-Alive:timeout=time”參數(shù)有關(guān),這些header信息也會(huì)被客戶端瀏覽器識(shí)別并處理,不過(guò)有些客戶端并不能按照服務(wù)器端的設(shè)置來(lái)處理,例如:MSIE大約60秒后會(huì)關(guān)閉keep-alive連接。細(xì)節(jié)見(jiàn):http://nginx.org/en/docs/http/ngx_http_core_module.html
(2)設(shè)置參數(shù):tcp_nodelay on;
用于激活tcp_ondelay功能,提高I/O性能。
syntax: tcp_nodelay on | off default: tcp_nodelay on; context: http,server,location參數(shù)作用:
默認(rèn)情況下當(dāng)數(shù)據(jù)發(fā)送時(shí),內(nèi)核并不會(huì)馬上發(fā)送,可能會(huì)等待更多的字節(jié)組成一個(gè)數(shù)據(jù)包,這樣可以提高I/O性能。但是,在每次只發(fā)送很少字節(jié)的業(yè)務(wù)場(chǎng)景中,使用tcp_nodelay功能,等待時(shí)間會(huì)比較長(zhǎng)。
參數(shù)生效條件:
激活或禁用TCP_NODELAY選項(xiàng),當(dāng)一個(gè)連接進(jìn)入keep-alive狀態(tài)時(shí)生效。細(xì)節(jié)見(jiàn)http://nginx.org/en/docs/http/ngx_http_core_module.html。
(3)設(shè)置參數(shù):client_header_timeout 15;
用于設(shè)置讀取客戶端請(qǐng)求頭數(shù)據(jù)的超時(shí)時(shí)間。此處的數(shù)值15,其單位是秒,為經(jīng)驗(yàn)參考值。
#client_header_timeout參數(shù)的官方說(shuō)明如下: syntax: client_header_timeout time; #參數(shù)語(yǔ)法 default: client_header_timeout 60s; #參數(shù)默認(rèn)大小 context: http,server #可以放置的標(biāo)簽段參數(shù)作用:
設(shè)置讀取客戶端請(qǐng)求頭數(shù)據(jù)的超時(shí)時(shí)間。如果超過(guò)這個(gè)時(shí)間,客戶端還沒(méi)有發(fā)送完整的header數(shù)據(jù),服務(wù)器端將返回“Request time out (408)”錯(cuò)誤,可指定一個(gè)超時(shí)時(shí)間,防止客戶端利用http協(xié)議進(jìn)行攻擊。細(xì)節(jié)見(jiàn):http://nginx.org/en/docs/http/ngx_http_core_module.html。
(4)設(shè)置參數(shù):client_body_timeout 15;
用于設(shè)置讀取客戶端請(qǐng)求主體的超時(shí)時(shí)間,默認(rèn)值60
#client_body_timeout參數(shù)的官方說(shuō)明如下: syntax: client_body_timeout time; #參數(shù)語(yǔ)法 default: client_body_timeout 60s; #默認(rèn)60 context: http,server,location #可以放置的標(biāo)簽段參數(shù)作用:
設(shè)置讀取客戶端請(qǐng)求主體的超時(shí)時(shí)間。這個(gè)超時(shí)僅僅為兩次成功的讀取操作之間的一個(gè)超時(shí),非請(qǐng)求整個(gè)主體數(shù)據(jù)的超時(shí)時(shí)間,如果在這個(gè)超時(shí)時(shí)間內(nèi),客戶端沒(méi)有發(fā)送任何數(shù)據(jù),Nginx將返回“Request time out(408)”錯(cuò)誤,默認(rèn)值60,細(xì)節(jié)見(jiàn):http://nginx.org/en/docs/http/ngx_http_core_module.html
(5)設(shè)置參數(shù):send_timeout 25;
用于指定響應(yīng)客戶端的超時(shí)時(shí)間。這個(gè)超時(shí)僅限于兩個(gè)連接活動(dòng)之間的時(shí)間,如果超過(guò)這個(gè)時(shí)間,客戶端沒(méi)有任何活動(dòng),Nginx將會(huì)關(guān)閉連接,默認(rèn)值為60秒,可以改為參考值25秒。
#send_timeout參數(shù)的官方說(shuō)明如下: syntax: send_timeout time; #參數(shù)語(yǔ)法 default: send_timeout 60s; #默認(rèn)值60 context: http,server,location #可以放置的標(biāo)簽段參數(shù)作用:
設(shè)置服務(wù)器端傳送HTTP響應(yīng)信息到客戶端的超時(shí)時(shí)間,這個(gè)超時(shí)僅僅為兩次成功握手后的一個(gè)超時(shí),非請(qǐng)求整個(gè)響應(yīng)數(shù)據(jù)的超時(shí)時(shí)間,如在這個(gè)超時(shí)時(shí)間內(nèi),客戶端沒(méi)有接收任何數(shù)據(jù),連接將被關(guān)閉。細(xì)節(jié)見(jiàn)http://nginx.org/en/docs/http/ngx_http_module.html。
備注:結(jié)合http原理畫(huà)圖講解超時(shí)參數(shù)
2.8 上傳文件大小的限制(動(dòng)態(tài)應(yīng)用)
下面我們學(xué)習(xí)如何調(diào)整上傳文件的大小(http Request body size)限制。
#首先,我們可以在Nginx主配置文件里加入如下參數(shù): client_max_body_size 8m;#具體大小根據(jù)公司的業(yè)務(wù)做調(diào)整,如果不清楚就先設(shè)置為8m把,有關(guān)客戶端請(qǐng)求主體的解釋在HTTP原理一節(jié)已經(jīng)解釋過(guò)了,一般情況下,HTTP的post方法在提交數(shù)據(jù)時(shí)才會(huì)攜帶請(qǐng)求主體信息。 #client_max_body_size參數(shù)的官方說(shuō)明如下: syntax: client_max_body_size size; #參數(shù)語(yǔ)法 default: client_max_body_size 1m; #默認(rèn)值1m context: http,server,location #可以放置的1標(biāo)簽段參數(shù)作用:
設(shè)置最大的允許的客戶端請(qǐng)求主體大小,在請(qǐng)求頭域有“Content-Length”,如果超過(guò)了此配置值,客戶端會(huì)受到413錯(cuò)誤,意思是請(qǐng)求的條目過(guò)大,有可能瀏覽器不能正確顯示。設(shè)置為0表示禁止檢查客戶端請(qǐng)求主體大小。此參數(shù)對(duì)提高服務(wù)器端的安全性有一定作用。細(xì)節(jié)見(jiàn)http://nginx.org/en/docs/http/ngx_http_core_module.html
2.9 FastCGI相關(guān)參數(shù)調(diào)優(yōu)(配合PHP引擎動(dòng)態(tài)服務(wù))
FastCGI參數(shù)是配合Nginx向后請(qǐng)求PHP動(dòng)態(tài)引擎服務(wù)的相關(guān)參數(shù)。Nginx FastCGI工作的邏輯圖如下圖所示:
此處講解的參數(shù)均為Nginx FastCGI客戶端向后請(qǐng)求PHP動(dòng)態(tài)引擎服務(wù)(php-fpm(FastCGI服務(wù)器端))的相關(guān)參數(shù),屬于Nginx的配置參數(shù)。下表是Nginx FastCGi常見(jiàn)參數(shù)的說(shuō)明。
FastCGI Cache資料見(jiàn)http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache。
FastCGI常見(jiàn)參數(shù)的Nginx配置示例如下:
[root@LNMP nginx]# cat /usr/local/nginx/conf/nginx.conf worker_processes 4; worker_cpu_affinity 0001 0010 0100 1000; worker_rlimit_nofile 65535; user nginx; events {use epoll;worker_connections 10240; } http {include mime.types;default_type application/octet-stream;sendfile on;tcp_nopush on;keepalive_timeout 65;tcp_nodelay on;client_header_timeout 15;client_body_timeout 15;send_timeout 15;log_format main '$remote_addr - $remote_user [$time_local] "$request"''$status $body_bytes_sent "$http_referer"''"$http_user_agent""$http_x_forwarded_for"';server_tokens off;fastcgi_connect_timeout 240; #Nginx允許fcgi連接超時(shí)時(shí)間fastcgi_send_timeout 240; #Nginx允許fcgi返回?cái)?shù)據(jù)的超時(shí)時(shí)間fastcgi_read_timeout 240; #Nginx讀取fcgi響應(yīng)信息的超時(shí)時(shí)間fastcgi_buffer_size 64k; #Nginx讀取響應(yīng)信息的緩沖區(qū)大小fastcgi_buffers 4 64k; #指定Nginx緩沖區(qū)的數(shù)量和大小fastcgi_busy_buffers_size 128k; #當(dāng)系統(tǒng)繁忙時(shí)buffer的大小fastcgi_temp_file_write_size 128k; #Nginx臨時(shí)文件的大小 # fastcgi_temp_path /data/ngx_fcgi_tmp; #指定Nginx臨時(shí)文件放置路徑fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d; #指定Nginx緩存放置路徑# webserver {listen 80;server_name www.yunjisuan.com;location / {root html;index index.php index.html index.htm;if (-f $request_filename/index.html){rewrite (.*) $1/index.html break;}if (-f $request_filename/index.php){rewrite (.*) $1/index.php;}if (!-f $request_filename){rewrite (.*) /index.php;}}access_log logs/web_www_access.log main;location ~ .*\.(php|php5)?$ {root html;fastcgi_pass 127.0.0.1:9000;fastcgi_index index.php;include fastcgi.conf;fastcgi_cache ngx_fcgi_cache; #開(kāi)啟fcgi緩存并起名叫ngx_fcgi_cache,很重要,有效降低CPU負(fù)載,并且防止502錯(cuò)誤發(fā)生。fastcgi_cache_valid 200 302 1h; #指定應(yīng)答代碼的緩存時(shí)間,1h=1小時(shí)fastcgi_cache_valid 301 1d; #1d=1天fastcgi_cache_valid any 1m; #and 1m:將其他應(yīng)答緩存1分鐘fastcgi_cache_min_uses 1; #待緩存內(nèi)容至少要被用戶請(qǐng)求過(guò)1次fastcgi_cache_use_stale error timeout invalid_header http_500; #當(dāng)遇到error,timeout,或者返回碼500時(shí),啟用過(guò)期緩存返回用戶(返回過(guò)期也比返回錯(cuò)誤強(qiáng)) # fastcgi_cache_key http://$host$request_uri; }}upstream www_yunjisuan {server 192.168.0.225:8000 weight=1;}server {listen 8000;server_name www.yunjisuan.com;location / { # root html;proxy_pass http://www_yunjisuan;proxy_set_header host $host;proxy_set_header x-forwarded-for $remote_addr;}access_log logs/proxy_www_access.log main;} }Nginx的FastCGI的相關(guān)參數(shù)和反向代理proxy的相關(guān)參數(shù)非常接近,同學(xué)們可以拿來(lái)比對(duì),一起理解。
2.10 配置Nginx gzip壓縮實(shí)現(xiàn)性能優(yōu)化
2.10.1 Nginx gzip壓縮功能介紹
Nginx gzip壓縮模塊提供了壓縮文件內(nèi)容的功能,用戶請(qǐng)求的內(nèi)容在發(fā)送到用戶客戶端之前,Nginx服務(wù)器會(huì)根據(jù)一些具體的策略實(shí)施壓縮,以節(jié)約網(wǎng)站出口帶寬,同時(shí)加快數(shù)據(jù)傳輸效率,來(lái)提升用戶訪問(wèn)體驗(yàn)。
2.10.2 Nginx gzip壓縮的優(yōu)點(diǎn)
- 提升網(wǎng)站用戶體驗(yàn):發(fā)送給用戶的內(nèi)容小了,用戶訪問(wèn)單位大小的頁(yè)面就加快了,用戶體驗(yàn)提升了,網(wǎng)站口碑就好了。
- 節(jié)約網(wǎng)站帶寬成本:數(shù)據(jù)是壓縮傳輸?shù)?#xff0c;因此節(jié)省了網(wǎng)站的帶寬流量成本,不過(guò)壓縮時(shí)會(huì)稍微消耗一些CPU資源,這個(gè)一般可以忽略。
此功能既能提升用戶體驗(yàn),又能使公司少花錢(qián),一舉多得。對(duì)于幾乎所有的Web服務(wù)來(lái)說(shuō),這是一個(gè)非常重要的功能,Apache服務(wù)也有此功能。
2.10.3 需要和不需要壓縮的對(duì)象
- 純文本內(nèi)容壓縮比很高,因此,純文本的內(nèi)容最好進(jìn)行壓縮,例如:html,js,css,xml,shtml等格式的文件。
- 被壓縮的純文本文件必須要大于1KB,由于壓縮算法的特殊原因,極小的文件壓縮后可能反而變大。
- 圖片,視頻(流媒體)等文件盡量不要壓縮,因?yàn)檫@些文件大多都是經(jīng)過(guò)壓縮的,如果再壓縮很可能不會(huì)減少或減少很少,或者有可能增大,同時(shí)壓縮時(shí)還會(huì)消耗大量的CPU,內(nèi)存資源。
2.10.4 參數(shù)介紹及配置說(shuō)明
此壓縮功能與早期Apache服務(wù)的mod_deflate壓縮功能很相似,Nginx的gzip壓縮功能依賴于ngx_http_gzip_module模塊,默認(rèn)已安裝。
對(duì)應(yīng)的壓縮參數(shù)說(shuō)明如下:
######壓縮的配置介紹###### gzip on; 開(kāi)啟gzip壓縮功能 gzip_min_length 1k; 設(shè)置允許壓縮的頁(yè)面最小字節(jié)數(shù),頁(yè)面字節(jié)數(shù)從header頭的Content-Length中獲取。默認(rèn)值0,表示不管頁(yè)面多大都進(jìn)行壓縮。建議設(shè)置成大于1K,如果小于1K可能會(huì)越壓越大。 gzip_buffers 4 16K; 壓縮緩沖區(qū)大小。表示申請(qǐng)4個(gè)單位為16K的內(nèi)存作為壓縮結(jié)果流緩存,默認(rèn)值是申請(qǐng)與原始數(shù)據(jù)大小相同的內(nèi)存空間來(lái)存儲(chǔ)gzip壓縮結(jié)果。 gzip_http_version 1.1; 壓縮版本(默認(rèn)1.1,前端為squid2.5時(shí)使用1.0),用于設(shè)置識(shí)別HTTP協(xié)議版本,默認(rèn)是1.1,目前大部分瀏覽器已經(jīng)支持GZIP解壓,使用默認(rèn)即可。 gzip_comp_level 2; 壓縮比率。用來(lái)指定gzip壓縮比,1壓縮比最小,處理速度最快;9壓縮比最大,傳輸速度快,但處理最慢,也比較消耗CPU資源。 gzip_types text/plain application/x-javascript text/css application/xml; 用來(lái)指定壓縮的類型,“text/html”類型總是會(huì)被壓縮,這個(gè)就是HTTP原理部分講的媒體類型。 gzip_vary on; vary header支持。該選項(xiàng)可以讓前端的緩存服務(wù)器緩存經(jīng)過(guò)gzip壓縮的頁(yè)面,例如用Squid緩存經(jīng)過(guò)Nginx壓縮的數(shù)據(jù)。不同的Nginx版本中,gzip_types的配置可能會(huì)有不同,上述配置示例適合Nginx 1.6.3。對(duì)應(yīng)的文件類型,請(qǐng)查看安裝目錄下的mime.types文件。
更多官方資源請(qǐng)看http://nginx.org/en/docs/http/ngx_http_gzip_module.html
2.10.5 Nginx壓縮配置效果檢查
可通過(guò)火狐瀏覽器+firebug插件+yslow插件查看gzip壓縮及expires緩存結(jié)果。提前安裝好yslow插件,開(kāi)啟監(jiān)控,然后打開(kāi)LNMP時(shí)安裝的博客地址,就可以看到如下圖所示的壓縮結(jié)果:
2.10.6 重要的前端網(wǎng)站調(diào)試工具介紹
常見(jiàn)的前端網(wǎng)站調(diào)試工具有如下幾種:
- Google瀏覽器(Chrome):通過(guò)該瀏覽器直接按F12鍵即可查看壓縮及緩存結(jié)果,另外,谷歌瀏覽器(Chrome)上也可以直接安裝yslow插件
- 火狐瀏覽器:在該瀏覽器上安裝firebug,yslow,即可進(jìn)行調(diào)試(火狐要用老版本比如V28)
- IE瀏覽器:在該瀏覽器上安裝httpwatch即可進(jìn)行調(diào)試(省略)
2.11 配置Nginx expires緩存實(shí)現(xiàn)性能優(yōu)化
2.11.1 Nginx expires功能介紹
- 簡(jiǎn)單說(shuō),Nginx expires的功能就是為用戶訪問(wèn)的網(wǎng)站內(nèi)容設(shè)定一個(gè)過(guò)期時(shí)間,當(dāng)用戶第一次訪問(wèn)這些內(nèi)容時(shí),會(huì)把這些內(nèi)容存儲(chǔ)在用戶瀏覽器本地,這樣用戶第二次及以后繼續(xù)訪問(wèn)該網(wǎng)站時(shí),瀏覽器會(huì)檢查加載已經(jīng)緩存在用戶瀏覽器本地的內(nèi)容,就不會(huì)去服務(wù)器下載了,直到緩存的內(nèi)容過(guò)期或被清除位置。
- 更深入的理解:expires的功能就是允許通過(guò)Nginx配置文件控制HTTP的“Expires”和“Cache-Control”響應(yīng)頭部?jī)?nèi)容,告訴客戶端瀏覽器是否緩存和緩存多久以內(nèi)訪問(wèn)的內(nèi)容。這個(gè)expires模塊控制Nginx服務(wù)器應(yīng)答時(shí)的expires頭內(nèi)容和Cache-Control頭的max-age指令。緩存的有效期可以設(shè)置為相對(duì)于源文件的最后修改時(shí)刻或客戶端的訪問(wèn)時(shí)刻。
- 這些HTTP頭向客戶端表明了額內(nèi)容的有效性和持久性。如果客戶端本地有內(nèi)容緩存,則內(nèi)容就可以從緩存而不是從服務(wù)器中讀取,然后客戶端會(huì)檢查緩存中的副本,看其是否過(guò)期或失效,以決定是否重新從服務(wù)器獲得內(nèi)容更新。
2.11.2 Nginx expires作用介紹
在網(wǎng)站的開(kāi)發(fā)和運(yùn)營(yíng)中,視頻,圖片,CSS,JS等網(wǎng)站元素的更改機(jī)會(huì)較少,特別是圖片,這時(shí)可以將圖片設(shè)置在客戶瀏覽器本地緩存365天或3650天,而將CSS,JS,html等代碼緩存10~30天。這樣用戶第一次打開(kāi)頁(yè)面后,會(huì)在本地的瀏覽器按照過(guò)期日期緩存相應(yīng)的內(nèi)容,下次用戶再打開(kāi)類似的頁(yè)面時(shí),重復(fù)的元素就無(wú)需下載了,從而加快用戶訪問(wèn)速度。用戶的訪問(wèn)請(qǐng)求和數(shù)據(jù)減少了,也可節(jié)省大量的服務(wù)器端帶寬。此功能同Apache的expires功能類似。
2.11.3 Nginx expires功能優(yōu)點(diǎn)
- expires可以降低網(wǎng)站的帶寬,節(jié)約成本。
- 加快用戶訪問(wèn)網(wǎng)站的速度,提升用戶訪問(wèn)體驗(yàn)。
- 服務(wù)器訪問(wèn)量降低了,服務(wù)器壓力就減輕了,服務(wù)器成本也會(huì)降低,甚至可以節(jié)約人力成本。
- 對(duì)于幾乎所有的Web服務(wù)來(lái)說(shuō),這是非常重要的功能之一,Apache服務(wù)也有此功能。
2.11.4 Nginx expires配置詳解
前面已經(jīng)介紹了expires的功能原理,接下來(lái)就來(lái)配置Nginx expires的功能。這里以location標(biāo)簽為例進(jìn)行講解,通過(guò)location URI規(guī)則將需要緩存的擴(kuò)展名列出來(lái),然后指定緩存時(shí)間。如果針對(duì)所有內(nèi)容設(shè)置緩存,也可以不用location。Nginx默認(rèn)安裝了expires功能。
(1)根據(jù)文件擴(kuò)展名進(jìn)行判斷,添加expires功能范例
范例1:
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {expires 3650d; }該范例的意思是當(dāng)用戶訪問(wèn)網(wǎng)站URL結(jié)尾的文件擴(kuò)展名為上述指定類型的額圖片時(shí),設(shè)置緩存3650天,即10年。
范例2:
location ~ .*\.(js|css)${expires 30d;}該范例的意思是當(dāng)用戶訪問(wèn)網(wǎng)站URL結(jié)尾的文件擴(kuò)展名為js,css類型的元素時(shí),設(shè)置緩存30天,即1個(gè)月。
(2)根據(jù)URL中的路徑(目錄)進(jìn)行判斷,添加expires功能范例
范例3:
location ~ ^/(images|javascript|js|css|flash|media|static)/ {expires 360d; }該范例的意思是當(dāng)用過(guò)戶訪問(wèn)網(wǎng)站URL中包含上述路徑(例:images,js,css,這些在服務(wù)器端是程序目錄)時(shí),把訪問(wèn)的內(nèi)容設(shè)置緩存360天,即1年。
2.11.5 Nginx expires配置效果檢查
檢查Nginx expires的方法和檢查Nginx gzip的方法相同。
通過(guò)火狐瀏覽器加yslow插件查看gzip壓縮及expires緩存結(jié)果時(shí),要提前安裝好火狐瀏覽器,并且要安裝好yslow插件,開(kāi)啟監(jiān)控,然后打開(kāi)LNMP時(shí)安裝的博客地址(帶有圖片,JS,CSS),就可以看到如下圖所示的緩存結(jié)果了。
在Linux客戶端可通過(guò)如下curl命令查看圖片URL的緩存header信息:
[root@localhost ~]# curl -I 192.168.0.220:8000 HTTP/1.1 200 OK Server: nginx Date: Wed, 30 Aug 2017 02:15:54 GMT Content-Type: text/html Content-Length: 18 Connection: keep-alive Last-Modified: Tue, 29 Aug 2017 19:37:44 GMT ETag: "59a5c288-12" Expires: Sat, 09 Sep 2017 02:15:54 GMT #緩存的過(guò)期時(shí)間 Cache-Control: max-age=864000 #緩存的總時(shí)間,單位秒 Accept-Ranges: bytes2.11.6 Nginx expires功能缺點(diǎn)及解決方法
- 幾乎所有的事物都是有兩面性,沒(méi)有十全十美的人和事。Nginx expires功能也不例外,雖然這個(gè)功能很好,但是也會(huì)給企業(yè)帶來(lái)一些困惑。
- 當(dāng)網(wǎng)站被緩存的頁(yè)面或數(shù)據(jù)更新了,此時(shí)用戶端看到的可能還是舊的已經(jīng)緩存的內(nèi)容,這樣就會(huì)影響用戶體驗(yàn),那么如何解決這個(gè)問(wèn)題呢?解決方法如下。
- 第一,對(duì)于經(jīng)常需要變動(dòng)的圖片等文件,可以縮短對(duì)象緩存時(shí)間,例如:谷歌和百度的首頁(yè)圖片經(jīng)常根據(jù)不同的日期換成一些節(jié)日的圖,所以這里可以將這個(gè)圖片設(shè)置為緩存期1天。
- 第二,當(dāng)網(wǎng)站改版或更新時(shí),可以在服務(wù)器將緩存的對(duì)象改名(網(wǎng)站代碼程序)。
- 對(duì)于網(wǎng)站的圖片,附件,一般不會(huì)被用戶直接修改,用戶層面上的修改圖片,實(shí)際上是重新傳到服務(wù)器,雖然內(nèi)容一樣但是是一個(gè)新的圖片名了。
- 網(wǎng)站改版升級(jí)會(huì)修改JS,CSS元素,若改版時(shí)對(duì)這些元素改了名,會(huì)使得前端的CDN及用戶端需要重新緩存內(nèi)容。
2.11.7 企業(yè)網(wǎng)站緩存日期曾經(jīng)的案例參考
若企業(yè)的業(yè)務(wù)和網(wǎng)站訪問(wèn)量不同,那么網(wǎng)站的緩存期時(shí)間設(shè)置也是不同的,比如,如下企業(yè)所用的緩存日期就是不一樣的。
- 51CTO:1周
- 新浪:15天
- 京東:25年
- 淘寶:10年
2.11.8 企業(yè)網(wǎng)站有可能不希望被緩存的內(nèi)容
- 廣告圖片,用于廣告服務(wù),都緩存了就不好控制展示了。
- 網(wǎng)站流量統(tǒng)計(jì)工具(JS代碼),都緩存了流量統(tǒng)計(jì)就不準(zhǔn)了。
- 更新很頻繁的文件(google的logo),這個(gè)如果按天,緩存效果還是顯著的。
三,Nginx日志相關(guān)優(yōu)化與安全
3.1 編寫(xiě)腳本實(shí)現(xiàn)Nginx access日志輪詢
當(dāng)用戶請(qǐng)求一個(gè)軟件時(shí),絕大多數(shù)軟件都會(huì)記錄用戶的訪問(wèn)情況,Nginx服務(wù)也不例外。Nginx軟件目前還沒(méi)有類似Apache的通過(guò)cronolog或rotatelog對(duì)日志分割處理的功能,但是,運(yùn)維人員可以利用腳本開(kāi)發(fā),Nginx的信號(hào)控制功能或reload重新加載,來(lái)實(shí)現(xiàn)日志的自動(dòng)切割,輪詢。
日志切割腳本如下:
[root@localhost nginx]# cat /server/scripts/cut_nginx_log.sh #!/bin/bash #日志切割腳本可掛定時(shí)任務(wù),每天00點(diǎn)整執(zhí)行Dateformat=`date +%Y%m%d` Basedir="/usr/local/nginx" Nginxlogdir="$Basedir/logs" Logname="access"[ -d $Nginxlogdir ] && cd $Nginxlogdir || exit 1 [ -f ${Logname}.log ] || exit 1 /bin/mv ${Logname}.log ${Dateformat}_${Logname}.log $Basedir/sbin/nginx -s reload[root@localhost nginx]# cat >>/var/spool/cron/root << KOF #cut nginx access log by Mr.chen 00 00 * * * /bin/bash /server/scripts/cut_nginx_log.sh >/dev/null 2>&13.2 不記錄不需要的訪問(wèn)日志
在實(shí)際工作中,對(duì)于負(fù)載均衡器健康節(jié)點(diǎn)檢查或某些特定文件(比如圖片,JS,CSS)的日志,一般不需要記錄下來(lái),因?yàn)樵诮y(tǒng)計(jì)PV時(shí)是按照頁(yè)面計(jì)算的,而且日志寫(xiě)入太頻繁會(huì)消耗大量磁盤(pán)I/O,降低服務(wù)的性能。
具體配置方法如下:
location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$ {access_log off; } #這里用location標(biāo)簽匹配不記錄日志的元素?cái)U(kuò)展名,然后關(guān)閉日志3.3 訪問(wèn)日志的權(quán)限設(shè)置
假如日志目錄為/app/logs,則授權(quán)方法如下:
chown -R root.root /app/logs chmod -R 700 /app/logs不需要在日志目錄上給Nginx用戶讀或?qū)懺S可,但很多網(wǎng)友都沒(méi)注意這個(gè)問(wèn)題,他們把該權(quán)限直接給了Nginx或Apache用戶,這就成為了安全隱患。
轉(zhuǎn)載于:https://www.cnblogs.com/tianakong/p/10001451.html
總結(jié)
以上是生活随笔為你收集整理的Linux实战教学笔记37:企业级Nginx Web服务优化实战(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php去除英文和标点,php 过滤英文标
- 下一篇: Idea 设置Eclipse快捷键(常用