Linux實戰教學筆記37:企業級Nginx Web服務優化實戰(上)


一,Nginx基本安全優化

1.1 調整參數隱藏Nginx軟件版本號信息

  • 一般來說,軟件的漏洞都和版本有關,這個很像汽車的缺陷,同一批次的要有問題就都有問題,別的批次可能就都是好的。因此,我們應盡量隱藏或消除Web服務對訪問用戶顯示各類敏感信息(例如Web軟件名稱及版本號等信息),這樣惡意的用戶就很難猜到他攻擊的服務器所用的是否有特定漏洞的軟件,或者是否有對應漏洞的某一特定版本,從而加強Web服務的安全性。這在武俠小說里,就相當於隱身術,你隱身了,對手就很難打着你了。
  • 想要隱身,首先要了解所使用軟件的版本號,對於Linux客戶端,可通過命令行查看Nginx版本號,最簡單的方法就是在Linux客戶端系統命令行執行如下curl命令:
[root@LNMP html]# curl -I 192.168.0.220
HTTP/1.1 200 OK
Server: nginx/1.6.2             #這里清晰的暴露了Web版本號(1.6.2)及軟件名稱(nginx)
Date: Wed, 23 Aug 2017 10:45:47 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/"

在Windows客戶端上,通過瀏覽器訪問Web服務時,若找不到頁面,默認報錯的信息如下圖所示:

QQ截圖20170825205242.png-31.5kB

以上雖然是不同的客戶端,但是都獲得了Nginx軟件名稱,而且查到了Nginx的版本號,這就使得Nginx Web服務的安全存在一定的風險,因此,應隱藏掉這些敏感信息或用一個其他的名字將其替代。例如,下面是百度搜索引擎網站Web軟件的更名做法:

[root@LNMP html]# curl -I baidu.com
HTTP/1.1 200 OK
Date: Fri, 25 Aug 2017 12:22:29 GMT
Server: Apache          #將Web服務軟件更名為了Apache,並且版本號也去掉了
[root@LNMP html]# curl -I -s www.baidu.com       
HTTP/1.1 200 OK
Server: bfe/1.0.8.18        #將Web服務軟件更名為了bfe,並且版本號改為1.0.8.18(閉源軟件名稱和版本就無所謂了)

門戶網站尚且如此,我們也學着隱藏或改掉應用服務軟件名和版本號把!事實上,還可以通過配置文件加參數來隱藏Nginx版本號。編輯nginx.conf配置文件增加參數,實現隱藏Nginx版本號的方式如下:

#在Nginx配置文件nginx.conf中的http標簽段內加入“server_tokens off”

http
{
...............
server_tokens off;
...............
}

此參數放置在http標簽內,作用是控制http response header內的Web服務版本信息的顯示,以及錯誤信息中Web服務版本信息的顯示。

server_tokens參數的官方說明如下:
syntax:     server_tokens on|off;   #此行為參數語法,on為開啟狀態,off為關閉狀態
default:    server_tokens on;       #此行意思是不配置該參數,軟件默認情況的結果
context:    http,server,location    #此行為server_tokens參數可以放置的位置參數作用:激活或禁止Nginx的版本信息顯示在報錯信息和Server的響應首部位置中。

官方資料地址:http://nginx.org/en/docs/http/ngx_http_core_module.html

配置完畢后保存,重新加載配置文件,再次通過curl查看,結果如下:

[root@LNMP nginx]# curl -I 192.168.0.220
HTTP/1.1 200 OK
Server: nginx                   #版本號已經消失
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/"

此時,瀏覽器的報錯提示中沒有了版本號,如下圖所示,修改成功。

QQ截圖20170825205203.png-34.3kB

1.2 更改源碼隱藏Nginx軟件名及版本號

隱藏了Nginx版本號后,更進一步,可以通過一些手段把Web服務軟件的名稱也隱藏起來,或者更改為其他Web服務軟件名以迷惑黑客。但軟件名字的隱藏修改,一般情況下不會有配置參數和入口,Nginx也不例外,這可能是由於商業及品牌展示等原因,軟件提供商不希望使用者把軟件名字隱藏起來。因此,此處需要更改Nginx源代碼,具體的解決方法如下:

1.2.1 第一步:依次修改3個Nginx源碼文件。

修改的第一個文件為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"      #修改為想要顯示的版本號
#define NGINX_VER          "nginx/" NGINX_VERSION
#將nginx修改為想要修改的軟件名稱。
#define NGINX_VAR          "NGINX"      #將nginx修改為想要修改的軟件名稱
#define NGX_OLDPID_EXT     ".oldbin"

修改后的結果如下:

[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"

修改的第二個文件是nginx-1.6.3/src/http/ngx_http_header_filter_module.c的第49行,需要修改的字符串內容如下:


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;           #修改本行結尾的nginx

通過sed替換修改,后如下:

[root@LNMP http]# grep -n 'Server: nginx' ngx_http_header_filter_module.c 
49:static char ngx_http_server_string[] = "Server: nginx" CRLF;
[root@LNMP http]# sed -i 's#Server: nginx#Server: yunjisuan#g' ngx_http_header_filter_module.c 
[root@LNMP http]# grep -n 'Server: yunjisuan' ngx_http_header_filter_module.c 
49:static char ngx_http_server_string[] = "Server: yunjisuan" CRLF;

修改的第三個文件是nginx-1.6.3/src/http/nginx_http_special_response.c,對面頁面報錯時,它會控制是否展開敏感信息。這里輸出修改前的信息ngx_http_special_response.c中的第21~30行,如下:

[root@LNMP http]# sed -n '21,30p' ngx_http_special_response.c 
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

修改后的結果如下:

[root@LNMP nginx-1.6.2]# sed -n '21,32p' src/http/ngx_http_special_response.c 
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       #此行將對外展示的Nginx名字更改為yunjisuan
"</body>" CRLF
"</html>" CRLF
;

1.2.2 第二步是修改后編輯軟件,使其生效

修改后再編譯安裝軟件,如果是已經安裝好的服務,需要重新編譯Nginx,配好配置,啟動服務。
再次使瀏覽器出現404錯誤,然后看訪問結果,如下圖所示:

QQ截圖20170826205843.png-33.2kB

如上面所示:Nginx的軟件和版本名都被改掉了,並且加上了本人的大名。
再看看Linux curl命令響應頭部信息,如下:

[root@LNMP conf]# curl -I localhost/xxx/
HTTP/1.1 404 Not Found
Server: yunjisuan/0.0.0.0           #也更改了
Date: Wed, 23 Aug 2017 15:33:54 GMT
Content-Type: text/html
Content-Length: 196
Connection: keep-alive

1.3 更改Nginx服務的默認用戶

  • 為了讓Web服務更安全,要盡可能地改掉軟件默認的所有配置,包括端口,用戶等。
  • 下面就來更改Nginx服務的默認用戶
  • 首先,查看Nginx服務對應的默認用戶。一般情況下,Nginx服務啟動后,默認使用的用戶是nobody,查看默認的配置文件,如下:
[root@LNMP conf]# cd /usr/local/nginx/conf/
[root@LNMP conf]# grep "#user" nginx.conf.default
#user  nobody;

為了防止黑客猜到這個Web服務的用戶,我們需要更改成特殊的用戶名,例如nginx或特殊點的inca,但是這個用戶必須是系統里事先存在的,下面以nginx用戶為例進行說明。

(1)為Nginx服務建立新用戶

useradd nginx -s /sbin/nologin -M
#不需要有系統登錄權限,應當禁止登陸。

(2)配置Nginx服務,讓其使用剛建立的nginx用戶

更改Nginx服務默認使用用戶,方法有二:

第一種:直接更改配置文件參數,將默認的#user nobody;改為如下內容:

user nginx nginx;

如果注釋或不設置上述參數,默認為nobody用戶,不推薦使用nobody用戶名,最好采用一個普通用戶,此處用大家習慣的,前面建立好的nginx用戶。

第二種:直接在編譯nginx軟件時指定編譯的用戶和組,命令如下:

./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module

#提示:
#前文在編譯Nginx服務時,就是這樣帶着參數的,因此無論配置文件中是否加參數,默認都是nginx用戶。

(3)檢查更改用戶的效果

重新加載配置后,檢查Nginx服務進程的對應用戶,如下:

[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      

通過查看上述更改后的Nginx進程,可以看到worker processes進程對應的用戶都變成了nginx。所以,我們有理由得出結論,上述的兩種方法都可設置Nginx的worker進程運行的用戶。當然,Nginx的主進程還是以root身份運行的。

二,根據參數優化Nginx服務性能

2.1 優化Nginx服務的worker進程個數

  • 在高並發,高訪問量的Web服務場景,需要事先啟動好更多的Nginx進程,以保證快速響應並處理大量並發用戶的請求。
  • 這類似於開飯店,在營業前,需要事先招聘一定數量的服務員准備接待顧客,但這里就有一個問題,如果飯店對客流沒有正確預估,就會導致一些問題發生,例如:服務員人數招聘多了,但是客流很少,那么服務員就可能很閑,沒事干,飯店的成本也高了;如果客流很大,而服務員人數少了,可能就接待不過來顧客,導致顧客吃飯體驗差。因此,飯店要根據客戶的流量及並發量來調整接待的服務人員數量,然后根據檢測顧客量變化及時調整到最佳配置。
  • Nginx服務就相當於飯店,網站用戶就相當於顧客,Nginx的進程就相當於服務員,下面就來優化Nginx進程的個數。

2.1.1 優化Nginx進程對應的配置

#優化Nginx進程對應Nginx服務的配置參數如下:
worker_processes 1;     #指定了Nginx要開啟的進程數,結尾數字就是進程個數

上述參數調整的是Nginx服務的worker進程數,Nginx有Master進程和worker進程之分,Master為管理進程,真正接待“顧客”的是worker進程。

2.1.2 優化Nginx進程個數的策略

  • 前面已經講解過,worker_processes參數大小的設置最好和網站的用戶數量相關聯,可如果是新配置,不知道網站的用戶數量該怎么辦呢?
  • 搭建服務器時,worker進程數最開始的設置可以等於CPU的核數,且worker進程數要多一些,這樣起始提供服務時就不會出現因為訪問量快速增加而臨時啟動新進程提供服務的問題,縮短了系統的瞬時開銷和提供服務的時間,提升了服務用戶的速度。高流量高並發場合也可以考慮將進程數提高至CPU核數*2,具體情況要根據實際的業務來選擇,因為這個參數除了要和CPU核數匹配外,也和硬盤存儲的數據及系統的負載有關,設置為CPU的核數是一個好的起始配置,這也是官方的建議。

2.1.3 查看Web服務器CPU硬件資源信息

下面介紹查看Linux服務器CPU總核數的方法:

(1)通過/proc/cpuinfo可查看CPU個數及總核數。查看CPU總核數的示例如下:

[root@LNMP ~]# grep processor /proc/cpuinfo 
processor	: 0
processor	: 1
processor	: 2
processor	: 3
[root@LNMP ~]# grep processor /proc/cpuinfo | wc -l
4               #表示為1顆CPU四核
[root@LNMP ~]# grep -c processor /proc/cpuinfo
4               #表示為1顆CPU四核

#查看CPU總顆數示例如下:
[root@LNMP ~]# grep "physical id" /proc/cpuinfo 
physical id	: 0     #物理ID一致,同一顆CPU
physical id	: 0     #物理ID一致,同一顆CPU
physical id	: 0     #物理ID一致,同一顆CPU
physical id	: 0     #物理ID一致,同一顆CPU
[root@LNMP ~]# grep "physical id" /proc/cpuinfo | sort | uniq | wc -l
1               #去重復,表示1顆CPU

(2)通過執行top命令,然后按數字1,即可顯示所有的CPU核數,如下:

QQ截圖20170827152136.png-52.9kB

2.1.4 實踐修改Nginx配置

假設服務器的CPU顆數為1顆,核數為4核,則初始的配置可通過查看默認的nginx.conf里的worker_processes數來了解,命令如下:

[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;        #提示可以通過vi修改

#優雅重啟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

#現在檢查修改后的worker進程數量,如下:
[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進程數為4個。Nginx Master主進程不包含在這個參數內,Nginx Master的主進程為管理進程,負責調度和管理worker進程。

有關worker_processes參數的官方說明如下:

syntax:         worker_processes number;    #此行為參數語法,number為數量
default:        worker_processes 1;     #此行意思是不匹配該參數,軟件默認情況數量為1
context:        main;   #此行為worker_processes參數可以放置的位置

worker_processes為定義worker進程數的數量,建議設置為CPU的核數或CPU核數*2,具體情況要根據實際的業務來選擇,因為這個參數,除了要和CPU核數匹配外,和硬盤存儲的數據以系統的負載也有關,設置為CPU的個數或核數是一個好的起始配置。From:http://nginx.org/en/docs/ngx_core_module.html

2.2 優化綁定不同的Nginx進程到不同的CPU上

  • 默認情況下,Nginx的多個進程有可能跑在某一個CPU或CPU的某一核上,導致Nginx進程使用硬件的資源不均,本節的優化是盡可能地分配不同的Nginx進程給不同的CPU處理,達到充分有效利用硬件的多CPU多核資源的目的。
  • 在優化不同的Nginx進程對應不同的CPU配置時,四核CPU服務器的參數配置參考如下:
worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000;

#worker_cpu_affinity就是配置Nginx進程與CPU親和力的參數,即把不同的進程分給不同的CPU處理。這里0001 0010 0100 1000是掩碼,分別代表第1,2,3,4核CPU,由於worker_processes進程數為4,因此,上述配置會把每個進程分配一核CPU處理,默認情況下進程不會綁定任何CPU,參數位置為main段。

四核和八核CPU服務器的參數配置參考如下:

#八核掩碼
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

#四核掩碼
worker_cpu_affinity 0001 0010 0100 1000;

worker_cpu_affinity 的作用是綁定不同的worker進程數到一組CPU上。通過設置bitmask控制進程允許使用的CPU,默認worker進程不會綁定到任何CPU(自動平均分配。)

2.2.1 實驗環境准備

主機名 IP地址 備注
Nginx 192.168.0.220 nginxWeb
測試機1 192.168.0.240 Webbench壓力測試
測試機2 192.168.0.245 Webbench壓力測試
#安裝webbench
tar xf webbench-1.5.tar.gz 
cd webbench-1.5
mkdir /usr/local/man
make install clean
which webbench.

虛擬機開啟4核心

QQ截圖20170827184049.png-7.5kB

2.2.2 第一步:不綁定worker進程進行壓力測試

#配置文件如下:(未綁定worker進程)
[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上執行如下命令:
[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 cached

   PID 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  
  

#在以上界面時按鍵盤的數值1鍵,出現如下界面:
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 cached

   PID 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      

在另外的兩台測試機器上同時進行壓力測試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/

結果如下:

QQ截圖20170827185601.png-36.8kB

2.2.3 第二步:綁定worker進程進行壓力測試

#配置文件如下(綁定worker進程)
[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;
        }
    }
}

在另外的兩台測試機器上同時進行壓力測試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/

結果如下:

QQ截圖20170827190217.png-32.6kB

根據圖示,我們基本可以看出,平均綁定worker進程和不綁定的實驗效果基本是一致的(CPU0是默認會被使用的)。原因在nginx在經過不斷的優化后,會自動對worker進程進行動態的平均分配。

2.2.4 第三步:修改nginx配置,將所有worker進程綁定到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;
        }
    }
}

在另外的兩台測試機器上同時進行壓力測試,命令如下:
webbench -c 2000 -t 60 http://192.168.0.220/

結果如下:

QQ截圖20170827190657.png-20.5kB

從上圖我們可以得知,worker進程的壓力被集中分配到了CPU3上。(CPU0是默認被使用的)

2.3 Nginx事件處理模型優化

  • Nginx的連接處理機制在不同的操作系統會采用不同的額I/O模型,在Linux下,Nginx使用epoll的I/O多路復用模型,在Freebsd中使用kqueue的I/O多路復用模型,在Solaris中使用/dev/poll方式的I/O多路復用模型,在Windows中使用的是icop,等等。
  • 要根據系統類型選擇不同的事件處理模型,可供使用的選擇有“use [kqueue|rtsig|epoll|/dev/poll|select|poll];”。因為教學使用的是CentOS 6.5 Linux,因此將Nginx的事件處理模型調整為epoll模型。
#具體的配置參數如下:
events      #events指令是設定Nginx的工作模式及連接數上限
{
    use epoll;     #use是一個事件模塊指令,用來指定Nginx的工作模式。Nginx支持的工作模式有select,poll,kqueue,epoll,rtsig和/dev/poll。其中select和poll都是標准的工作模式,kqueue和epoll是高效的工作模式,不同的是epoll用在Linux平台上,而kqueue用在BSD系統中。對於Linux系統Linux2.6+內核,推薦選擇epoll工作模式,這是高性能高並發的設置
}

根據Nginx官方文檔建議,也可以不指定事件處理模型,Nginx會自動選擇最佳的事件處理模型服務。
對於使用連接進程的方法,通常不需要進行任何設置,Nginx會自動選擇最有效辦法。

2.4 調整Nginx單個進程允許的客戶端最大連接數

接下來,調整Nginx單個進程允許的客戶端最大連接數,這個控制連接數的參數為work_connections。
worker_connections的值要根據具體服務器性能和程序的內存使用量來指定(一個進程啟動使用的內存根據程序確定),如下:

events  #events指令是設定Nginx的工作模式和連接數上線
{
    worker_connections 20480;
    #worker_connections也是個事件模塊指令,用於定義Nginx每個進程的最大連接數,默認是1024.最大客戶端連接數由worker_processes和worker_connections決定,即Max_client=  worker_processes*worker_connections。進程的最大連接數受Linux系統進程的最大打開文件數限制,在執行操作系統命令“ulimit   -HSn    65535”或配置相應文件后,worker_connections的設置才能生效。
}

下面是worker_connections的官方說明

參數語法:worker_connections number
默認配置:worker_connections 512
放置位置:events

說明:

worker_connections用來設置一個worker process支持的最大並發連接數,這個連接數包括了所有鏈接,例如:代理服務器的連接,客戶端的連接等,實際的並發連接數除了受worker_connections參數控制外,還和最大打開文件數worker_rlimit_nofile有關(見下文),Nginx總並發連接=worker數量*worker_connections。
參考資料:http://nginx.org/en/docs/ngx_core_module.html

2.5 配置Nginx worker進程最大打開文件數

接下來,調整配置Nginx worker進程的最大打開文件數,這個控制連接數的參數為worker_rlimit_nofile。該參數的實際配置如下:

worker_rlimit_nofile 65535;
#最大打開文件數,可設置為系統優化后的ulimit     -HSn的結果

下面是worker_rlimit_nofile number的官方說明:

參數語法:worker_rlimit_nofile number
默認配置:無
放置位置:主標簽段

說明:此參數的作用是改變worker processes能打開的最大文件數
參考資料:http://nginx.org/en/docs/ngx_core_module.html

備注:
Linux系統文件最大打開數設置:ulimit -n 65535

2.5.1 實驗環境准備

主機名 IP地址 備注
Nginx 192.168.0.220 nginxWeb
測試機1 192.168.0.240 Webbench壓力測試
測試機2 192.168.0.245 Webbench壓力測試

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連接數。同學們注意多開幾個虛擬機進行壓力測試。不然的話,web服務器還沒出問題,你測試服務器先down掉了。

2.5.2 測試nginx服務連接數的極值

#使用這個命令可以抓取nginx的連接數
[root@LNMP nginx]# netstat -antp | grep nginx | wc -l
554
[root@LNMP nginx]# netstat -antp | grep nginx | wc -l
471

逐漸提高壓力,抓連接數,看看nginx啥時候down

2.6 開啟高效文件傳輸模式

(1)設置參數:sendfile on;

sendfile參數用於開啟文件的高效傳輸模式。同時將tcp_nopush和tcp_nodelay兩個指令設置為on,可防止網絡及磁盤I/O阻塞,提升Nginx工作效率。

#sendfile參數的官方說明如下:
syntax:     sendfile on | off;   #參數語法
default:    sendfile off;        #參數默認大小
context:    http,server,location,if in location #可以放置的標簽段

參數作用:
激活或禁用sendfile()功能功能。sendfile()是作用於兩個文件描述符之間的數據拷貝函數,這個拷貝操作是在內核之中的,被稱為“零拷貝”,sendfile()比read和write函數要高效很多,因為,read和write函數要把數據拷貝到應用層再進行操作。相關控制參數還有sendfile_max_chunk,同學們可以執行查詢。細節見http://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile

(2)設置參數:tcp_nopush on;

#tcp_nopush參數的官方說明如下:
syntax:     tcp_nopush on | off;    #參數語法
default:    tcp_nopush off;         #參數默認大小
context:    http,server,location    #可以放置的標簽段

參數作用:
激活或禁用Linux上的TCP_CORK socket選項,此選項僅僅當開啟sendfile時才生效,激活這個tcp_nopush參數可以允許把http response header和文件的開始部分放在一個文件里發布,其積極的作用是減少網絡報文段的數量。細節見http://nginx.org/en/docs/http/ngx_http_core_module.html。

2.7 優化Nginx連接參數,調整連接超時時間

2.7.1 什么是連接超時

  • 先來個比喻吧,某飯店請了服務員招待顧客,但是現在飯店不景氣,此時,為多余的服務員發工資使得成本被提高,想減少飯店開支成本就得解雇服務員。
  • 這里的服務員就相當於Nginx服務建立的連接,當服務器建立的連接沒有接收處理請求時,可在指定的時間內就讓它超時自動退出。還有當Nginx和FastCGI服務建立連接請求PHP時,如果因為一些原因(負載高,停止響應),FastCGI服務無法給Nginx返回數據,此時可以通過配置Nginx服務參數使其不會死等,因為前面用過戶還等着它返回數據呢,例如,可設置為如果請求FastCGI 10秒內不能返回數據,那么Nginx就中斷本次請求,向用戶匯報取不到數據的錯誤。

2.7.2 連接超時的作用

  • 將無用的連接設置為盡快超時,可以保護服務器的系統資源(CPU,內存,磁盤)。
  • 當連接很多時,及時斷掉那些已經建立好的但又長時間不做事的連接,以減少其占用的服務器資源,因為服務器維護連接也是消耗資源的。
  • 有時黑客或惡意用戶攻擊網站,就會不斷地和服務器建立多個連接,消耗連接數,但是啥也不干,大量消耗服務器的資源,此時就應該及時斷掉這些惡意占用資源的連接。
  • LNMP環境中,如果用戶請求了動態服務,則Nginx就會建立連接,請求FastCGI服務以及后端MySQL服務,此時這個Nginx連接就要設定一個超時時間,在用戶容忍的時間內返回數據,或者再多等一會兒后端服務返回數據,具體的策略要根據具體業務進行具體分析。當然了,后端的FastCGI服務及MySQL服務也有對連接的超時控制。

簡單的說,連接超時是服務的一種自我管理,自我保護的重要機制。

2.7.3 連接超時帶來的問題,以及不同程序連接設定知識

  • 服務器建立新連接也是要消耗資源的,因此,超時設置得太短而並發很大,就會導致服務器瞬間無法響應用戶的請求,導致用戶體驗下降。
  • 企業生產有些PHP程序站點會希望設置成短連接,因為PHP程序建立連接消耗的資源和時間相對要少些。而對於Java程序站點來說,一般建議設置長連接,因為Java程序建立連接消耗的資源和時間更多,這是語言運行機制決定的。

2.7.4 Nginx連接超時的參數設置

(1)設置參數:keepalive_timeout 60;

用於設置客戶端連接保持會話的超時時間為60秒。超過這個時間,服務器會關閉該連接,此數值為參考值。

keepalive_timeout參數的官方說明如下:
syntax: keepalive_timeout  timeout [header_timeout] #參數語法
default: keepalive_timeout 75s;     #參數默認大小
context: http,serverr,location      #可以放置的標簽段

參數作用:

  • keep-alive可以使客戶端到服務器端已經建立的連接一直工作不退出,當服務器有持續請求時,keep-alive會使用已經建立的連接提供服務,從而避免服務器重新建立新連接處理請求。
  • 此參數設置一個keep-alive(客戶端連接在服務器端保持多久后退出),其單位是秒,和HTTP響應header域的“Keep-Alive:timeout=time”參數有關,這些header信息也會被客戶端瀏覽器識別並處理,不過有些客戶端並不能按照服務器端的設置來處理,例如:MSIE大約60秒后會關閉keep-alive連接。細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html

(2)設置參數:tcp_nodelay on;

用於激活tcp_ondelay功能,提高I/O性能。

#tcp_nodelay參數的官方說明如下:
syntax:     tcp_nodelay on | off    #參數語法
default:    tcp_nodelay on;         #參數默認大小
context:    http,server,location    #可以放置的標簽段

參數作用:
默認情況下當數據發送時,內核並不會馬上發送,可能會等待更多的字節組成一個數據包,這樣可以提高I/O性能。但是,在每次只發送很少字節的業務場景中,使用tcp_nodelay功能,等待時間會比較長。
參數生效條件:
激活或禁用TCP_NODELAY選項,當一個連接進入keep-alive狀態時生效。細節見http://nginx.org/en/docs/http/ngx_http_core_module.html。

(3)設置參數:client_header_timeout 15;

用於設置讀取客戶端請求頭數據的超時時間。此處的數值15,其單位是秒,為經驗參考值。

#client_header_timeout參數的官方說明如下:
syntax:     client_header_timeout time; #參數語法
default:    client_header_timeout 60s;  #參數默認大小
context:    http,server         #可以放置的標簽段

參數作用:
設置讀取客戶端請求頭數據的超時時間。如果超過這個時間,客戶端還沒有發送完整的header數據,服務器端將返回“Request time out (408)”錯誤,可指定一個超時時間,防止客戶端利用http協議進行攻擊。細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html。

(4)設置參數:client_body_timeout 15;

用於設置讀取客戶端請求主體的超時時間,默認值60

#client_body_timeout參數的官方說明如下:
syntax:     client_body_timeout time;   #參數語法
default:    client_body_timeout 60s;    #默認60
context:    http,server,location    #可以放置的標簽段

參數作用:
設置讀取客戶端請求主體的超時時間。這個超時僅僅為兩次成功的讀取操作之間的一個超時,非請求整個主體數據的超時時間,如果在這個超時時間內,客戶端沒有發送任何數據,Nginx將返回“Request time out(408)”錯誤,默認值60,細節見:http://nginx.org/en/docs/http/ngx_http_core_module.html

(5)設置參數:send_timeout 25;

用於指定響應客戶端的超時時間。這個超時僅限於兩個連接活動之間的時間,如果超過這個時間,客戶端沒有任何活動,Nginx將會關閉連接,默認值為60秒,可以改為參考值25秒。

#send_timeout參數的官方說明如下:
syntax:     send_timeout    time;   #參數語法
default:    send_timeout    60s;    #默認值60
context:    http,server,location    #可以放置的標簽段

參數作用:
設置服務器端傳送HTTP響應信息到客戶端的超時時間,這個超時僅僅為兩次成功握手后的一個超時,非請求整個響應數據的超時時間,如在這個超時時間內,客戶端沒有接收任何數據,連接將被關閉。細節見http://nginx.org/en/docs/http/ngx_http_module.html。

QQ截圖20170827232141.png-614kB

備注:結合http原理畫圖講解超時參數

2.8 上傳文件大小的限制(動態應用)

下面我們學習如何調整上傳文件的大小(http Request body size)限制。

#首先,我們可以在Nginx主配置文件里加入如下參數:
client_max_body_size 8m;

#具體大小根據公司的業務做調整,如果不清楚就先設置為8m把,有關客戶端請求主體的解釋在HTTP原理一節已經解釋過了,一般情況下,HTTP的post方法在提交數據時才會攜帶請求主體信息。
#client_max_body_size參數的官方說明如下:
syntax:     client_max_body_size size;  #參數語法
default:    client_max_body_size 1m;    #默認值1m
context:   http,server,location        #可以放置的1標簽段

參數作用:
設置最大的允許的客戶端請求主體大小,在請求頭域有“Content-Length”,如果超過了此配置值,客戶端會受到413錯誤,意思是請求的條目過大,有可能瀏覽器不能正確顯示。設置為0表示禁止檢查客戶端請求主體大小。此參數對提高服務器端的安全性有一定作用。細節見http://nginx.org/en/docs/http/ngx_http_core_module.html

2.9 FastCGI相關參數調優(配合PHP引擎動態服務)

FastCGI參數是配合Nginx向后請求PHP動態引擎服務的相關參數。Nginx FastCGI工作的邏輯圖如下圖所示:

QQ截圖20170828004930.png-77.1kB

此處講解的參數均為Nginx FastCGI客戶端向后請求PHP動態引擎服務(php-fpm(FastCGI服務器端))的相關參數,屬於Nginx的配置參數。下表是Nginx FastCGi常見參數的說明。

QQ截圖20170828005612.png-445.9kB

QQ截圖20170828005628.png-208.8kB

FastCGI Cache資料見http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_cache。

FastCGI常見參數的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連接超時時間
    fastcgi_send_timeout 240;           #Nginx允許fcgi返回數據的超時時間
    fastcgi_read_timeout 240;           #Nginx讀取fcgi響應信息的超時時間
    fastcgi_buffer_size 64k;            #Nginx讀取響應信息的緩沖區大小
    fastcgi_buffers 4 64k;              #指定Nginx緩沖區的數量和大小
    fastcgi_busy_buffers_size 128k;     #當系統繁忙時buffer的大小
    fastcgi_temp_file_write_size 128k;  #Nginx臨時文件的大小
#   fastcgi_temp_path 	/data/ngx_fcgi_tmp; #指定Nginx臨時文件放置路徑
    fastcgi_cache_path 	/data/ngx_fcgi_cache	levels=2:2	keys_zone=ngx_fcgi_cache:512m	inactive=1d;    #指定Nginx緩存放置路徑
    
# web

    server {
        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;       #開啟fcgi緩存並起名叫ngx_fcgi_cache,很重要,有效降低CPU負載,並且防止502錯誤發生。
		fastcgi_cache_valid 200 302 1h; #指定應答代碼的緩存時間,1h=1小時
		fastcgi_cache_valid 301 1d;     #1d=1天
		fastcgi_cache_valid any 1m;     #and 1m:將其他應答緩存1分鍾
		fastcgi_cache_min_uses 1;       #待緩存內容至少要被用戶請求過1次
		fastcgi_cache_use_stale error timeout invalid_header http_500;  #當遇到error,timeout,或者返回碼500時,啟用過期緩存返回用戶(返回過期也比返回錯誤強)
#		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;
    }
}

QQ截圖20170829203733.png-161.9kB

Nginx的FastCGI的相關參數和反向代理proxy的相關參數非常接近,同學們可以拿來比對,一起理解。

2.10 配置Nginx gzip壓縮實現性能優化

2.10.1 Nginx gzip壓縮功能介紹

Nginx gzip壓縮模塊提供了壓縮文件內容的功能,用戶請求的內容在發送到用戶客戶端之前,Nginx服務器會根據一些具體的策略實施壓縮,以節約網站出口帶寬,同時加快數據傳輸效率,來提升用戶訪問體驗。

2.10.2 Nginx gzip壓縮的優點

  • 提升網站用戶體驗:發送給用戶的內容小了,用戶訪問單位大小的頁面就加快了,用戶體驗提升了,網站口碑就好了。
  • 節約網站帶寬成本:數據是壓縮傳輸的,因此節省了網站的帶寬流量成本,不過壓縮時會稍微消耗一些CPU資源,這個一般可以忽略。

此功能既能提升用戶體驗,又能使公司少花錢,一舉多得。對於幾乎所有的Web服務來說,這是一個非常重要的功能,Apache服務也有此功能。

2.10.3 需要和不需要壓縮的對象

  • 純文本內容壓縮比很高,因此,純文本的內容最好進行壓縮,例如:html,js,css,xml,shtml等格式的文件。
  • 被壓縮的純文本文件必須要大於1KB,由於壓縮算法的特殊原因,極小的文件壓縮后可能反而變大。
  • 圖片,視頻(流媒體)等文件盡量不要壓縮,因為這些文件大多都是經過壓縮的,如果再壓縮很可能不會減少或減少很少,或者有可能增大,同時壓縮時還會消耗大量的CPU,內存資源。

2.10.4 參數介紹及配置說明

此壓縮功能與早期Apache服務的mod_deflate壓縮功能很相似,Nginx的gzip壓縮功能依賴於ngx_http_gzip_module模塊,默認已安裝。

對應的壓縮參數說明如下:

#######壓縮的配置介紹######
gzip on;
#開啟gzip壓縮功能
gzip_min_length 1k;
#設置允許壓縮的頁面最小字節數,頁面字節數從header頭的Content-Length中獲取。默認值0,表示不管頁面多大都進行壓縮。建議設置成大於1K,如果小於1K可能會越壓越大。
gzip_buffers 4 16K;
#壓縮緩沖區大小。表示申請4個單位為16K的內存作為壓縮結果流緩存,默認值是申請與原始數據大小相同的內存空間來存儲gzip壓縮結果。
gzip_http_version 1.1;
#壓縮版本(默認1.1,前端為squid2.5時使用1.0),用於設置識別HTTP協議版本,默認是1.1,目前大部分瀏覽器已經支持GZIP解壓,使用默認即可。
gzip_comp_level 2;
#壓縮比率。用來指定gzip壓縮比,1壓縮比最小,處理速度最快;9壓縮比最大,傳輸速度快,但處理最慢,也比較消耗CPU資源。
gzip_types text/plain application/x-javascript text/css application/xml;
#用來指定壓縮的類型,“text/html”類型總是會被壓縮,這個就是HTTP原理部分講的媒體類型。
gzip_vary on;
#vary header支持。該選項可以讓前端的緩存服務器緩存經過gzip壓縮的頁面,例如用Squid緩存經過Nginx壓縮的數據。

不同的Nginx版本中,gzip_types的配置可能會有不同,上述配置示例適合Nginx 1.6.3。對應的文件類型,請查看安裝目錄下的mime.types文件。

更多官方資源請看http://nginx.org/en/docs/http/ngx_http_gzip_module.html

2.10.5 Nginx壓縮配置效果檢查

可通過火狐瀏覽器+firebug插件+yslow插件查看gzip壓縮及expires緩存結果。提前安裝好yslow插件,開啟監控,然后打開LNMP時安裝的博客地址,就可以看到如下圖所示的壓縮結果:

QQ截圖20170830002722.png-456kB

2.10.6 重要的前端網站調試工具介紹

常見的前端網站調試工具有如下幾種:

  • Google瀏覽器(Chrome):通過該瀏覽器直接按F12鍵即可查看壓縮及緩存結果,另外,谷歌瀏覽器(Chrome)上也可以直接安裝yslow插件
  • 火狐瀏覽器:在該瀏覽器上安裝firebug,yslow,即可進行調試(火狐要用老版本比如V28)
  • IE瀏覽器:在該瀏覽器上安裝httpwatch即可進行調試(省略)

2.11 配置Nginx expires緩存實現性能優化

2.11.1 Nginx expires功能介紹

  • 簡單說,Nginx expires的功能就是為用戶訪問的網站內容設定一個過期時間,當用戶第一次訪問這些內容時,會把這些內容存儲在用戶瀏覽器本地,這樣用戶第二次及以后繼續訪問該網站時,瀏覽器會檢查加載已經緩存在用戶瀏覽器本地的內容,就不會去服務器下載了,直到緩存的內容過期或被清除位置。
  • 更深入的理解:expires的功能就是允許通過Nginx配置文件控制HTTP的“Expires”和“Cache-Control”響應頭部內容,告訴客戶端瀏覽器是否緩存和緩存多久以內訪問的內容。這個expires模塊控制Nginx服務器應答時的expires頭內容和Cache-Control頭的max-age指令。緩存的有效期可以設置為相對於源文件的最后修改時刻或客戶端的訪問時刻。
  • 這些HTTP頭向客戶端表明了額內容的有效性和持久性。如果客戶端本地有內容緩存,則內容就可以從緩存而不是從服務器中讀取,然后客戶端會檢查緩存中的副本,看其是否過期或失效,以決定是否重新從服務器獲得內容更新。

2.11.2 Nginx expires作用介紹

在網站的開發和運營中,視頻,圖片,CSS,JS等網站元素的更改機會較少,特別是圖片,這時可以將圖片設置在客戶瀏覽器本地緩存365天或3650天,而將CSS,JS,html等代碼緩存10~30天。這樣用戶第一次打開頁面后,會在本地的瀏覽器按照過期日期緩存相應的內容,下次用戶再打開類似的頁面時,重復的元素就無需下載了,從而加快用戶訪問速度。用戶的訪問請求和數據減少了,也可節省大量的服務器端帶寬。此功能同Apache的expires功能類似。

2.11.3 Nginx expires功能優點

  • expires可以降低網站的帶寬,節約成本。
  • 加快用戶訪問網站的速度,提升用戶訪問體驗。
  • 服務器訪問量降低了,服務器壓力就減輕了,服務器成本也會降低,甚至可以節約人力成本。
  • 對於幾乎所有的Web服務來說,這是非常重要的功能之一,Apache服務也有此功能。

2.11.4 Nginx expires配置詳解

前面已經介紹了expires的功能原理,接下來就來配置Nginx expires的功能。這里以location標簽為例進行講解,通過location URI規則將需要緩存的擴展名列出來,然后指定緩存時間。如果針對所有內容設置緩存,也可以不用location。Nginx默認安裝了expires功能。

(1)根據文件擴展名進行判斷,添加expires功能范例

范例1:

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
    expires 3650d;
}

該范例的意思是當用戶訪問網站URL結尾的文件擴展名為上述指定類型的額圖片時,設置緩存3650天,即10年。

范例2:

location ~ .*\.(js|css)$
 {
    expires 30d;
 }

該范例的意思是當用戶訪問網站URL結尾的文件擴展名為js,css類型的元素時,設置緩存30天,即1個月。

(2)根據URL中的路徑(目錄)進行判斷,添加expires功能范例

范例3:

location ~ ^/(images|javascript|js|css|flash|media|static)/
{
    expires 360d;
}

該范例的意思是當用過戶訪問網站URL中包含上述路徑(例:images,js,css,這些在服務器端是程序目錄)時,把訪問的內容設置緩存360天,即1年。

2.11.5 Nginx expires配置效果檢查

檢查Nginx expires的方法和檢查Nginx gzip的方法相同。
通過火狐瀏覽器加yslow插件查看gzip壓縮及expires緩存結果時,要提前安裝好火狐瀏覽器,並且要安裝好yslow插件,開啟監控,然后打開LNMP時安裝的博客地址(帶有圖片,JS,CSS),就可以看到如下圖所示的緩存結果了。

QQ截圖20170830191330.png-11.7kB

在Linux客戶端可通過如下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      #緩存的過期時間
Cache-Control: max-age=864000               #緩存的總時間,單位秒
Accept-Ranges: bytes

2.11.6 Nginx expires功能缺點及解決方法

  • 幾乎所有的事物都是有兩面性,沒有十全十美的人和事。Nginx expires功能也不例外,雖然這個功能很好,但是也會給企業帶來一些困惑。
  • 當網站被緩存的頁面或數據更新了,此時用戶端看到的可能還是舊的已經緩存的內容,這樣就會影響用戶體驗,那么如何解決這個問題呢?解決方法如下。
  • 第一,對於經常需要變動的圖片等文件,可以縮短對象緩存時間,例如:谷歌和百度的首頁圖片經常根據不同的日期換成一些節日的圖,所以這里可以將這個圖片設置為緩存期1天。
  • 第二,當網站改版或更新時,可以在服務器將緩存的對象改名(網站代碼程序)。
  • 對於網站的圖片,附件,一般不會被用戶直接修改,用戶層面上的修改圖片,實際上是重新傳到服務器,雖然內容一樣但是是一個新的圖片名了。
  • 網站改版升級會修改JS,CSS元素,若改版時對這些元素改了名,會使得前端的CDN及用戶端需要重新緩存內容。

2.11.7 企業網站緩存日期曾經的案例參考

若企業的業務和網站訪問量不同,那么網站的緩存期時間設置也是不同的,比如,如下企業所用的緩存日期就是不一樣的。

  • 51CTO:1周
  • 新浪:15天
  • 京東:25年
  • 淘寶:10年

2.11.8 企業網站有可能不希望被緩存的內容

  • 廣告圖片,用於廣告服務,都緩存了就不好控制展示了。
  • 網站流量統計工具(JS代碼),都緩存了流量統計就不准了。
  • 更新很頻繁的文件(google的logo),這個如果按天,緩存效果還是顯著的。

三,Nginx日志相關優化與安全

3.1 編寫腳本實現Nginx access日志輪詢

當用戶請求一個軟件時,絕大多數軟件都會記錄用戶的訪問情況,Nginx服務也不例外。Nginx軟件目前還沒有類似Apache的通過cronolog或rotatelog對日志分割處理的功能,但是,運維人員可以利用腳本開發,Nginx的信號控制功能或reload重新加載,來實現日志的自動切割,輪詢。

日志切割腳本如下:

[root@localhost nginx]# cat /server/scripts/cut_nginx_log.sh 
#!/bin/bash
#日志切割腳本可掛定時任務,每天00點整執行

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>&1

3.2 不記錄不需要的訪問日志

在實際工作中,對於負載均衡器健康節點檢查或某些特定文件(比如圖片,JS,CSS)的日志,一般不需要記錄下來,因為在統計PV時是按照頁面計算的,而且日志寫入太頻繁會消耗大量磁盤I/O,降低服務的性能。

具體配置方法如下:

location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$
{
    access_log  off;
}
#這里用location標簽匹配不記錄日志的元素擴展名,然后關閉日志

3.3 訪問日志的權限設置

假如日志目錄為/app/logs,則授權方法如下:

chown -R root.root /app/logs
chmod -R 700 /app/logs

不需要在日志目錄上給Nginx用戶讀或寫許可,但很多網友都沒注意這個問題,他們把該權限直接給了Nginx或Apache用戶,這就成為了安全隱患。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM