目錄
軟件調優
1.隱藏 Nginx 版本號
2.隱藏 Nginx 版本號和軟件名
3.更改 Nginx 服務的默認用戶
4.優化 Nginx worker 進程數
5.綁定 Nginx 進程到不同的 CPU 上
6.優化 Nginx 處理事件模型
7.優化 Nginx 單個進程允許的最大連接數
8.優化 Nginx worker 進程最大打開文件數
9.優化服務器域名的散列表大小
10.開啟高效文件傳輸模式
11.優化 Nginx 連接超時時間
12.限制上傳文件的大小
13.FastCGI 相關參數調優
14.配置 Nginx gzip 壓縮
15.配置 Nginx expires 緩存
16.優化 Nginx日志(日志切割)
17.優化 Nginx 站點目錄
18.配置 Nginx 防盜鏈
19.配置 Nginx 錯誤頁面優雅顯示
20.優化 Nginx 文件權限
21.Nginx 防爬蟲優化
22.控制 Nginx 並發連接數
23. 集群代理優化
系統內核參數優化
Nginx軟件調優
1. 隱藏 Nginx 版本號
為什么要隱藏 Nginx 版本號:一般來說,軟件的漏洞都與版本有關,隱藏版本號是為了防止惡意用戶利用軟件漏洞進行攻擊
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off; # 隱藏版本號
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
}
}
}
...
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
[root@localhost ~]# curl -I 127.0.0.1 # 查看是否隱藏版本號
HTTP/1.1 404 Not Found
Server: nginx
Date: Thu, 25 May 2017 05:23:03 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
2.隱藏 Nginx 版本號和軟件名
為什么要隱藏 Nginx 版本號和軟件名:一般來說,軟件的漏洞都與版本有關,隱藏版本號是為了防止惡意用戶利用軟件漏洞進行攻擊,而軟件名可以進行修改,否則黑客知道是 Nginx 服務器更容易進行攻擊,需要注意的是,隱藏 Nginx 軟件名需要重新編譯安裝 Nginx ,如果沒有該方面需求盡量不要做
1) 修改:/usr/local/src/nginx-1.6.3/src/core/nginx.h
#define NGINX_VERSION "8.8.8.8" # 修改為想要顯示的版本號 #define NGINX_VER "Google/" NGINX_VERSION # 修改為想要顯示的軟件名 #define NGINX_VAR "Google" # 修改為想要顯示的軟件名
2) 修改:/usr/local/src/nginx-1.6.3/src/http/ngx_http_header_filter_module.c
static char ngx_http_server_string[] = "Server: Google" CRLF; # 修改為想要顯示的軟件名 static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
3) 修改:/usr/local/src/nginx-1.6.3/src/http/ngx_http_special_response.c
static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER "(www.google.com)</center>" CRLF # 此行定義對外展示的內容 "</body>" CRLF "</html>" CRLF ; static u_char ngx_http_error_tail[] = "<hr><center>Google</center>" CRLF # 此行定義對外展示的軟件名 "</body>" CRLF "</html>" CRLF ;
4) 重新編譯 Nginx
cd /usr/local/src/nginx-1.6.3 ./configure --user=nginx --group=nginx --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module make && make install /usr/local/nginx/sbin/nginx
3.更改 Nginx 服務的默認用戶
為什么要更改 Nginx 服務的默認用戶:就像更改 ssh 的默認 22 端口一樣,增加安全性,Nginx 服務的默認用戶是 nobody ,我們更改為 nginx
1) 添加 nginx 用戶
useradd -s /sbin/nologin -M nginx
2) 更改 Nginx 配置文件
[root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf
worker_processes 1;
user nginx nginx; # 指定Nginx服務的用戶和用戶組
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
}
}
}
3) 重新加載 Nginx
[root@localhost ~]# /usr/local/nginx/sbin/nginx -t [root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
4) 驗證是否生效
[root@localhost ~]# ps aux | grep nginx root 8901 0.0 0.1 45036 1784 ? Ss 13:54 0:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 8909 0.0 0.1 45460 1828 ? S 13:59 0:00 nginx: worker process # Nginx進程的所屬用戶為nginx
4.優化 Nginx worker 進程數
Nginx 有 Master 和 worker 兩種進程,Master 進程用於管理 worker 進程,worker 進程用於 Nginx 服務
worker 進程數應該設置為等於 CPU 的核數,高流量並發場合也可以考慮將進程數提高至 CPU 核數 * 2
[root@localhost ~]# grep -c processor /proc/cpuinfo # 查看CPU核數 2 [root@localhost ~]# vim /usr/local/nginx/conf/nginx.conf # 設置worker進程數 worker_processes 2; user nginx nginx; ...... [root@localhost ~]# /usr/local/nginx/sbin/nginx -t # 重新加載Nginx [root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload [root@localhost ~]# ps -ef | grep nginx | grep -v grep # 驗證是否為設置的進程數 root 8901 1 0 13:54 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginx nginx 8937 8901 0 14:14 ? 00:00:00 nginx: worker process nginx 8938 8901 0 14:14 ? 00:00:00 nginx: worker process
5.綁定 Nginx 進程到不同的 CPU 上
為什么要綁定 Nginx 進程到不同的 CPU 上 :默認情況下,Nginx 的多個進程有可能跑在某一個 CPU 或 CPU 的某一核上,導致 Nginx 進程使用硬件的資源不均,因此綁定 Nginx 進程到不同的 CPU 上是為了充分利用硬件的多 CPU 多核資源的目的。
[root@localhost ~]# grep -c processor /proc/cpuinfo # 查看CPU核數 2 worker_processes 2; # 2核CPU的配置 worker_cpu_affinity 01 10; worker_processes 4; # 4核CPU的配置 worker_cpu_affinity 0001 0010 0100 1000; worker_processes 8; # 8核CPU的配置 worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 1000000; [root@localhost ~]# /usr/local/nginx/sbin/nginx -t [root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload
[root@localhost ~]# cd /usr/local/src/ # 進行壓力測試,教程:http://os.51cto.com/art/201202/317803.htm [root@localhost src]# wget http://home.tiscali.cz/~cz210552/distfiles/webbench-1.5.tar.gz [root@localhost src]# tar -zxvf webbench-1.5.tar.gz [root@localhost src]# cd webbench-1.5 [root@localhost src]# yum install -y ctags gcc [root@localhost src]# mkdir -m 644 -p /usr/local/man/man1 [root@localhost src]# make && make install [root@localhost src]# webbench -c 10000 -t 60 http://192.168.5.131/
[root@localhost ~]# top # 按1查看CPU調度結果,這里是虛擬機測試,效果並不太明顯 top - 14:44:46 up 4:40, 3 users, load average: 0.01, 0.32, 0.24 Tasks: 85 total, 1 running, 84 sleeping, 0 stopped, 0 zombie Cpu0 : 0.8%us, 0.8%sy, 0.0%ni, 97.9%id, 0.3%wa, 0.0%hi, 0.2%si, 0.0%st Cpu1 : 0.6%us, 0.7%sy, 0.0%ni, 98.1%id, 0.0%wa, 0.0%hi, 0.5%si, 0.0%st Mem: 1534840k total, 304824k used, 1230016k free, 3932k buffers Swap: 204792k total, 0k used, 204792k free, 191364k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4319 root 20 0 98308 3932 2964 S 3.2 0.3 0:15.76 sshd 18989 root 20 0 15016 1292 1008 R 1.6 0.1 0:00.04 top 1 root 20 0 19232 1388 1112 S 0.0 0.1 0:02.19 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.08 kthreadd 3 root RT 0 0 0 0 S 0.0 0.0 0:00.61 migration/0 4 root 20 0 0 0 0 S 0.0 0.0 0:03.60 ksoftirqd/0 5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 6 root RT 0 0 0 0 S 0.0 0.0 0:00.50 watchdog/0
6.優化 Nginx 處理事件模型
Nginx 的連接處理機制在不同的操作系統會采用不同的 I/O 模型,要根據不同的系統選擇不同的事件處理模型,可供選擇的事件處理模型有:kqueue 、rtsig 、epoll 、/dev/poll 、select 、poll ,其中 select 和 epoll 都是標准的工作模型,kqueue 和 epoll 是高效的工作模型,不同的是 epoll 用在 Linux 平台上,而 kqueue 用在 BSD 系統中。
(1) 在 Linux 下,Nginx 使用 epoll 的 I/O 多路復用模型
(2) 在 Freebsd 下,Nginx 使用 kqueue 的 I/O 多路復用模型
(3) 在 Solaris 下,Nginx 使用 /dev/poll 方式的 I/O 多路復用模型
(4) 在 Windows 下,Nginx 使用 icop 的 I/O 多路復用模型
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
events {
use epoll;
}
......
7.優化 Nginx 單個進程允許的最大連接數
(1) 控制 Nginx 單個進程允許的最大連接數的參數為 worker_connections ,這個參數要根據服務器性能和內存使用量來調整
(2) 進程的最大連接數受 Linux 系統進程的最大打開文件數限制,只有執行了 "ulimit -HSn 65535" 之后,worker_connections 才能生效
(3) 連接數包括代理服務器的連接、客戶端的連接等,Nginx 總並發連接數 = worker 數量 * worker_connections, 總數保持在3w左右
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 2;
worker_cpu_affinity 01 10;
user nginx nginx;
events {
use epoll;
worker_connections 15000;
}
......
8.優化 Nginx worker 進程最大打開文件數
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 2;
worker_cpu_affinity 01 10;
worker_rlimit_nofile 65535; # worker 進程最大打開文件數,可設置為優化后的 ulimit -HSn 的結果
user nginx nginx;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
}
}
}
9.優化服務器域名的散列表大小
如下,如果在 server_name 中配置了一個很長的域名,那么重載 Nginx 時會報錯,因此需要使用 server_names_hash_max_size 來解決域名過長的問題,該參數的作用是設置存放域名的最大散列表的存儲的大小,根據 CPU 的一級緩存大小來設置。
server {
listen 80;
server_name www.abcdefghijklmnopqrst.com; # 配置一個很長的域名
location / {
root html/www;
index index.html index.htm;
}
}
[root@localhost conf]# /usr/local/nginx/sbin/nginx -t # 如果配置的域名很長會出現如下錯誤 nginx: [emerg] could not build the server_names_hash, you should increase server_names_hash_bucket_size: 64 nginx: configuration file /usr/local/nginx/conf/nginx.conf test failed
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
http {
include mime.types;
server_names_hash_bucket_size 512; # 配置在 http 區塊,默認是 512kb ,一般設置為 cpu 一級緩存的 4-5 倍,一級緩存大小可以用 lscpu 命令查看
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
include vhosts/*.conf;
}
10.開啟高效文件傳輸模式
(1) sendfile 參數用於開啟文件的高效傳輸模式,該參數實際上是激活了 sendfile() 功能,sendfile() 是作用於兩個文件描述符之間的數據拷貝函數,這個拷貝操作是在內核之中的,被稱為 "零拷貝" ,sendfile() 比 read 和 write 函數要高效得多,因為 read 和 write 函數要把數據拷貝到應用層再進行操作
(2) tcp_nopush 參數用於激活 Linux 上的 TCP_CORK socket 選項,此選項僅僅當開啟 sendfile 時才生效,tcp_nopush 參數可以允許把 http response header 和文件的開始部分放在一個文件里發布,以減少網絡報文段的數量
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
http {
include mime.types;
server_names_hash_bucket_size 512;
default_type application/octet-stream;
sendfile on; # 開啟文件的高效傳輸模式
tcp_nopush on; # 激活 TCP_CORK socket 選擇
tcp_nodelay on; #數據在傳輸的過程中不進緩存
keepalive_timeout 65;
server_tokens off;
include vhosts/*.conf;
}
11.優化 Nginx 連接超時時間
1. 什么是連接超時
(1) 舉個例子,某飯店請了服務員招待顧客,但是現在飯店不景氣,因此要解雇掉一些服務員,這里的服務員就相當於 Nginx 服務建立的連接
(2) 當服務器建立的連接沒有接收處理請求時,可以在指定的時間內讓它超時自動退出
2. 連接超時的作用
(1) 將無用的連接設置為盡快超時,可以保護服務器的系統資源(CPU、內存、磁盤)
(2) 當連接很多時,及時斷掉那些建立好的但又長時間不做事的連接,以減少其占用的服務器資源
(3) 如果黑客攻擊,會不斷地和服務器建立連接,因此設置連接超時以防止大量消耗服務器的資源
(4) 如果用戶請求了動態服務,則 Nginx 就會建立連接,請求 FastCGI 服務以及后端 MySQL 服務,設置連接超時,使得在用戶容忍的時間內返回數據
3. 連接超時存在的問題
(1) 服務器建立新連接是要消耗資源的,因此,連接超時時間不宜設置得太短,否則會造成並發很大,導致服務器瞬間無法響應用戶的請求
(2) 有些 PHP 站點會希望設置成短連接,因為 PHP 程序建立連接消耗的資源和時間相對要少些
(3) 有些 Java 站點會希望設置成長連接,因為 Java 程序建立連接消耗的資源和時間要多一些,這時由語言的運行機制決定的
4. 設置連接超時
(1) keepalive_timeout :該參數用於設置客戶端連接保持會話的超時時間,超過這個時間服務器會關閉該連接
(2) client_header_timeout :該參數用於設置讀取客戶端請求頭數據的超時時間,如果超時客戶端還沒有發送完整的 header 數據,服務器將返回 "Request time out (408)" 錯誤
(3) client_body_timeout :該參數用於設置讀取客戶端請求主體數據的超時時間,如果超時客戶端還沒有發送完整的主體數據,服務器將返回 "Request time out (408)" 錯誤
(4) send_timeout :用於指定響應客戶端的超時時間,如果超過這個時間,客戶端沒有任何活動,Nginx 將會關閉連接
(5) tcp_nodelay :默認情況下當數據發送時,內核並不會馬上發送,可能會等待更多的字節組成一個數據包,這樣可以提高 I/O 性能,但是,在每次只發送很少字節的業務場景中,使用 tcp_nodelay 功能,等待時間會比較長
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
http {
include mime.types;
server_names_hash_bucket_size 512;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
tcp_nodelay on;
client_header_timeout 15;
client_body_timeout 15;
send_timeout 25;
include vhosts/*.conf;
}
12.限制上傳文件的大小
client_max_body_size 用於設置最大的允許客戶端請求主體的大小,在請求首部中有 "Content-Length" ,如果超過了此配置項,客戶端會收到 413 錯誤,即請求的條目過大
worker_processes 2;
worker_cpu_affinity 01 10;
user nginx nginx;
error_log logs/error.log error;
events {
use epoll;
worker_connections 20480;
}
http {
include mime.types;
server_names_hash_bucket_size 512;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server_tokens off;
client_max_body_size 8m; # 設置客戶端最大的請求主體大小為8M
include vhosts/*.conf;
}
13.FastCGI 相關參數調優
當 LNMP 組合工作時,首先是用戶通過瀏覽器輸入域名請求 Nginx Web 服務,如果請求的是靜態資源,則由 Nginx 解析返回給用戶;如果是動態請求(如 PHP),那么 Nginx 就會把它通過 FastCGI 接口發送給 PHP 引擎服務(即 php-fpm)進行解析,如果這個動態請求要讀取數據庫數據,那么 PHP 就會繼續向后請求 MySQL 數據庫,以讀取需要的數據,並最終通過 Nginx 服務把獲取的數據返回給用戶,這就是 LNMP 環境的基本請求流程。
FastCGI 介紹:CGI 通用網關接口,是 HTTP 服務器與其他機器上的程序服務通信交流的一種工具,CGI 接口的性能較差,每次 HTTP 服務器遇到動態程序時都需要重新啟動解析器來執行解析,之后結果才會被返回 HTTP 服務器,因此就有了 FastCGI ,FastCGI 是一個在 HTTP 服務器和動態腳本語言間通信的接口,主要是把動態語言和 HTTP 服務器分離開來,使得 HTTP 服務器專一地處理靜態請求,提高整體性能,在 Linux 下,FastCGI 接口即為 socket ,這個 socket 可以是文件 socket 也可以是 IP socket
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
fastcgi_connect_timeout 240; # Nginx服務器和后端FastCGI服務器連接的超時時間
fastcgi_send_timeout 240; # Nginx允許FastCGI服務器返回數據的超時時間,即在規定時間內后端服務器必須傳完所有的數據,否則Nginx將斷開這個連接
fastcgi_read_timeout 240; # Nginx從FastCGI服務器讀取響應信息的超時時間,表示連接建立成功后,Nginx等待后端服務器的響應時間
fastcgi_buffer_size 64k; # Nginx FastCGI 的緩沖區大小,用來讀取從FastCGI服務器端收到的第一部分響應信息的緩沖區大小
fastcgi_buffers 4 64k; # 設定用來讀取從FastCGI服務器端收到的響應信息的緩沖區大小和緩沖區數量
fastcgi_busy_buffers_size 128k; # 用於設置系統很忙時可以使用的 proxy_buffers 大小
fastcgi_temp_file_write_size 128k; # FastCGI 臨時文件的大小
# fastcti_temp_path /data/ngx_fcgi_tmp; # FastCGI 臨時文件的存放路徑
fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g; # 緩存目錄
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
}
location ~ .*\.(php|php5)?$ {
root html/www;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
fastcgi_cache ngx_fcgi_cache; # 緩存FastCGI生成的內容,比如PHP生成的動態內容
fastcgi_cache_valid 200 302 1h; # 指定http狀態碼的緩存時間,這里表示將200和302緩存1小時
fastcgi_cache_valid 301 1d; # 指定http狀態碼的緩存時間,這里表示將301緩存1天
fastcgi_cache_valid any 1m; # 指定http狀態碼的緩存時間,這里表示將其他狀態碼緩存1分鍾
fastcgi_cache_min_uses 1; # 設置請求幾次之后響應被緩存,1表示一次即被緩存
fastcgi_cache_use_stale error timeout invalid_header http_500; # 定義在哪些情況下使用過期緩存
fastcgi_cache_key http://$host$request_uri; # 定義 fastcgi_cache 的 key
}
}
}
[root@localhost ~]# pkill php-fpm [root@localhost ~]# /usr/local/php/sbin/php-fpm
14.配置 Nginx gzip 壓縮
Nginx gzip 壓縮模塊提供了壓縮文件內容的功能,用戶請求的內容在發送到客戶端之前,Nginx 服務器會根據一些具體的策略實施壓縮,以節約網站出口帶寬,同時加快數據傳輸效率,來提升用戶訪問體驗,需要壓縮的對象有 html 、js 、css 、xml 、shtml ,圖片和視頻盡量不要壓縮,因為這些文件大多都是已經壓縮過的,如果再壓縮可能反而變大,另外,壓縮的對象必須大於 1KB,由於壓縮算法的特殊原因,極小的文件壓縮后可能反而變大
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
http {
gzip on; # 開啟壓縮功能
gzip_min_length 1k; # 允許壓縮的對象的最小字節
gzip_buffers 4 32k; # 壓縮緩沖區大小,表示申請4個單位為16k的內存作為壓縮結果的緩存
gzip_http_version 1.1; # 壓縮版本,用於設置識別HTTP協議版本
gzip_comp_level 9; # 壓縮級別,1級壓縮比最小但處理速度最快,9級壓縮比最高但處理速度最慢
gzip_types text/css text/xml application/javascript; # 允許壓縮的媒體類型
gzip_vary on; # 該選項可以讓前端的緩存服務器緩存經過gzip壓縮的頁面,例如用代理服務器緩存經過Nginx壓縮的數據
}
檢查壓縮:可以用 Google 瀏覽器按 F12 查看,也可以在 Google 瀏覽器安裝 yslow 插件(yslow.org)


15.配置 Nginx expires 緩存
(1) Nginx expires 的功能就是為用戶訪問的網站內容設定一個過期時間,當用戶第一次訪問這些內容時,會把這些內容存儲在用戶瀏覽器本地,這樣用戶第二次及以后繼續訪問該網站時,瀏覽器會檢查加載已經緩存在用戶瀏覽器本地的內容,就不會去服務器下載了,直到緩存的內容過期或被清除為止
(2) 不希望被緩存的內容:廣告圖片、網站流量統計工具、更新很頻繁的文件
(3) 緩存日期參考:51CTO 緩存 1 周,新浪緩存 15 天,京東緩存 25 年,淘寶緩存 10 年
server {
listen 80;
server_name www.abc.com abc.com;
root html/www;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ # 緩存的對象
{
expires 3650d; # 緩存的時間,3650天,即10年
}
}
使用 Google 瀏覽器安裝 yslow 插件來查看:

16.優化 Nginx access 日志
1. 配置日志切割
[root@localhost ~]# vim /usr/local/nginx/conf/cut_nginx_log.sh #!/bin/bash savepath_log='/usr/local/clogs' nglogs='/usr/local/nginx/logs' mkdir -p $savepath_log/$(date +%Y)/$(date +%m) mv $nglogs/access.log $savepath_log/$(date +%Y)/$(date +%m)/access.$(date +%Y%m%d).log mv $nglogs/error.log $savepath_log/$(date +%Y)/$(date +%m)/error.$(date +%Y%m%d).log kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
[root@localhost ~]# crontab -e # 每天凌晨0點執行腳本 0 0 * * * /bin/sh /usr/local/nginx/conf/cut_nginx_log.sh > /dev/null 2>&1
2. 不記錄不需要的訪問日志
location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$ {
access_log off;
}
3. 設置訪問日志的權限
chown -R root.root /usr/local/nginx/logs chmod -R 700 /usr/local/nginx/logs
17.優化 Nginx 站點目錄
1. 禁止解析指定目錄下的指定程序
location ~ ^/data/.*\.(php|php5|sh|pl|py)$ { # 根據實際來禁止哪些目錄下的程序,且該配置必須寫在 Nginx 解析 PHP 的配置前面
deny all;
}
2. 禁止訪問指定目錄
location ~ ^/data/.*\.(php|php5|sh|pl|py)$ { # 根據實際來禁止哪些目錄下的程序,且該配置必須寫在 Nginx 解析 PHP 的配置前面
deny all;
}
3. 限制哪些 IP 不能訪問網站
location ~ ^/wordpress { # 相對目錄,表示只允許 192.168.1.1 訪問網站根目錄下的 wordpress 目錄
allow 192.168.1.1/24;
deny all;
}
18.配置 Nginx 防盜鏈
什么是防盜鏈:簡單地說,就是某些不法網站未經許可,通過在其自身網站程序里非法調用其他網站的資源,然后在自己的網站上顯示這些調用的資源,使得被盜鏈的那一端消耗帶寬資源 (1) 根據 HTTP referer 實現防盜鏈:referer 是 HTTP的一個首部字段,用於指明用戶請求的 URL 是從哪個頁面通過鏈接跳轉過來的
(2) 根據 cookie 實現防盜鏈:cookie 是服務器貼在客戶端身上的 "標簽" ,服務器用它來識別客戶端
根據 referer 配置防盜鏈:
#第一種,匹配后綴
location ~ .*\.(gif|jpg|jpeg|png|bm|swf|flv|rar|zip|gz|bz2)$ { # 指定需要使用防盜鏈的媒體資源
access_log off; # 不記錄防盜鏈的日志
expires 15d; # 設置緩存時間
valid_referers none blocked *.test.com *.abc.com; # 表示這些地址可以訪問上面的媒體資源
if ($invalid_referer) { # 如果地址不如上面指定的地址就返回403
return 403
}
}
#第二種,綁定目錄
location /images {
root /web/www/img;
vaild_referers nono blocked *.spdir.com *.spdir.top;
if ($invalid_referer) {
return 403;
}
}
19.配置 Nginx 錯誤頁面優雅顯示
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
......
http {
location / {
root html/www;
index index.html index.htm;
error_page 400 401 402 403 404 405 408 410 412 413 414 415 500 501 502 503 506 = http://www.xxxx.com/error.html;
# 將這些狀態碼的頁面鏈接到 http://www.xxxx.com/error.html ,也可以單獨指定某個狀態碼的頁面,如 error_page 404 /404.html
}
}
20.優化 Nginx 文件權限
為了保證網站不受木馬入侵,所有文件的用戶和組都應該為 root ,所有目錄的權限是 755 ,所有文件的權限是 644
[root@localhost ~]# chown -R root.root /usr/local/nginx/.... # 根據實際來調整 [root@localhost ~]# chmod 755 /usr/local/nginx/.... [root@localhost ~]# chmod 644 /usr/local/nginx/....
21.Nginx 防爬蟲優化
我們可以根據客戶端的 user-agents 首部字段來阻止指定的爬蟲爬取我們的網站\
if ($http_user_agent ~* "qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot") {
return 403;
}
22.控制 Nginx 並發連接數
1. 限制單個 IP 的並發連接數
[root@localhost ~]# cat /usr/local/nginx/conf/nginx.conf
....
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
limit_conn_zone $binary_remote_addr zone=addr:10m; # 用於設置共享內存區域,addr 是共享內存區域的名稱,10m 表示共享內存區域的大小
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
limit_conn addr 1; # 限制單個IP的並發連接數為1
}
}
}
2. 限制虛擬主機總連接數
....
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
limit_conn_zone $server_name zone=perserver:10m;
server {
listen 80;
server_name www.abc.com;
location / {
root html/www;
index index.html index.htm;
limit_conn perserver 2; # 設置虛擬主機連接數為2
}
}
}
23. 集群代理優化
upstream bbs_com_pool{ #定義服務器池
ip_hash; #會話保持(當服務器集群中沒有會話池時,且代理的是動態數據就必須寫ip_hash,反之什么也不用寫)
#fair #智能分配(第三方,需要下載upstream_fair模塊)根據后端服務器的響應時間來調度
#url_hash #更具URL的結果來分配請求(每個url定向到同一個服務器,提高后端緩存服務器的效率,本身不支持,需要安裝nginx_hash)
#當算法為ip_hash不能有 weight backup
server 192.168.10.1:80; #默認weight為1
server 192.168.10.3:80 weight=5; #weight表示權重
server 192.168.10.4:80 down; #down:不參與本次輪詢
server 192.168.10.5:80 down backup; #backup:當任何一台主機出現故障,將進行切換替換
server 192.168.10.6:80 max_fails=3 fail_timeout=20s; #max_fails最大失敗請求次數(默認為1),fail_timeout失敗超時時間
server 192.168.10.7:8080;
}
stream{
upstream cluster {
# hash $remote_addr consistent; //保持 session 不變,四層開啟
server 192.168.1.2:80 max_fails=3 fail_timeout=30s;
server 192.168.1.3:80 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
proxy_pass cluster;
proxy_connect_timeout 1s;
proxy_timeout 3s;
}
location {
proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header; 當發生其中任何一種錯誤,將轉交給下一個服務器
proxy_redirect off;
proxy_set_header Host &$host; #設置后端服務器的真實地址
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded_For &proxy_add_x_forwarded_for;
client_body_buffer_size 128k; #緩沖區大小,本地保存大小
proxy_connect_timeout 90; #發起握手等待的響應時間
proxy_read_timeout 90; #建立連接后等待后端服務器響應時間(其實是后端等候處理的時間)
proxy_send_timeout 90; #給定時間內后端服務器必須響應,否則斷開
proxy_buffer_size 4k; #proxy緩沖區大小
proxy_buffers 4 32k; #緩沖區個數和大小
proxy_busy_buffers_size 64k; #系統繁忙時buffer的臨時大小,官方要求proxy_buffer_size*2
proxy_temp_file_write_size 64k; #proxy臨時文件的大小
}
}
系統內核參數優化
vim /etc/sysctl.conf net.ipv4.tcp_syncookies = 1 fs.file-max = 999999 net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_tw_recycle = 1 net.core.somaxconn=262114 net.core.netdev_max_backlog=262114 net.ipv4.tcp_max_syn_backlog = 262114 net.ipv4.tcp_max_orphans=262114 net.ipv4.tcp_synack_retries=1 net.ipv4.tcp_syn_retries=1 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_fin_timeout = 30 net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_rmem = 10240 87380 12582912 net.ipv4.tcp_wmem = 10240 87380 12582912 net.core.netdev_max_backlog = 8096 net.core.rmem_default = 6291456 net.core.wmem_default = 6291456 net.core.rmem_max = 12582912 net.core.wmem_max = 12582912
參數詳解
net.ipv4.tcp_syncookies = 1:選項用於設置開啟SYN cookies,當出現SYN等待隊列溢出時,啟用cookies進行處理; fs.file-max = 999999:這個參數表示進程(比如一個worker進程)可以同時打開的最大句柄數,這個參數直線限制最大並發連接數,需根據實際情況配置; net.ipv4.tcp_max_tw_buckets =6000:這個參數用來設定timewait數量,如果超過這個數字,TIME_WAIT套接字將立刻被清除並打印警告信息。該參數默認為180 000,過多的TIME_WAIT套接字會使Web服務器變慢; net.ipv4.tcp_tw_recycle=1:這個參數用於設置啟用timewait快速回收; net.ipv4.tcp_tw_reuse = 1:這個參數設置為1,表示允許將TIME-WAIT狀態的socket重新用於新的TCP連接,這對於服務器來說很有意義,因為服務器上總會有大量TIME-WAIT狀態的連接; net.core.somaxconn=262114 :選項默認值是128,這個參數用於調節系統同時發起的TCP連接數,在高並發的請求中,默認的值可能會導致鏈接超時或者重傳,因此需要結合高並發請求數來調節此值; net.core.netdev_max_backlog=262114:該選項表示每個網絡接口接收數據包的速率比內核處理這些包的速率快時,允許發送到隊列數據包的最大數目; net.ipv4.tcp_max_syn_backlog =262114:這個參數表示TCP三次握手建立階段接受SYN請求隊列的最大長度,默認為1024,將其設置得大一些可以使出現Nginx繁忙來不及accept新連接的情況時,Linux不至於丟失客戶端發起的連接請求; net.ipv4.tcp_max_orphans=262114:選項用於設定系統中最多有多少個TCP套接字不被關聯到任何一個用戶文件句柄上。如果超過這個數字,孤立鏈接將立即被復位並輸出警告信息。這個限制指示為了防止簡單的DOS攻擊,不用過分依靠這個限制甚至認為的減小這個值,更多的情況是增加這個值; net.ipv4.tcp_synack_retries=1:內核放棄連接之前發送SYN+ACK包的數量; net.ipv4.tcp_syn_retries=1:內核放棄連接之前發送SYN包的數量; net.ipv4.tcp_keepalive_time = 600:這個參數表示當keepalive啟用時,TCP發送keepalive消息的頻度。默認是2小時,若將其設置的小一些,可以更快地清理無效的連接; net.ipv4.tcp_fin_timeout = 30:這個參數表示當服務器主動關閉連接時,socket保持在FIN-WAIT-2狀態的最大時間; net.ipv4.ip_local_port_range = 1024 61000:這個參數定義了在UDP和TCP連接中本地(不包括連接的遠端)端口的取值范圍; net.ipv4.tcp_rmem = 10240 87380 12582912:這個參數定義了TCP接受緩存(用於TCP接受滑動窗口)的最小值、默認值、最大值; net.ipv4.tcp_wmem = 10240 87380 12582912:這個參數定義了TCP發送緩存(用於TCP發送滑動窗口)的最小值、默認值、最大值; net.core.netdev_max_backlog = 8096:當網卡接受數據包的速度大於內核處理的速度時,會有一個隊列保存這些數據包。這個參數表示該隊列的最大值; net.core.rmem_default = 6291456:這個參數表示內核套接字接受緩存區默認的大小; net.core.wmem_default = 6291456:這個參數表示內核套接字發送緩存區默認的大小; net.core.rmem_max = 12582912:這個參數表示內核套接字接受緩存區的最大大小; net.core.wmem_max = 12582912:這個參數表示內核套接字發送緩存區的最大大小; net.ipv4.tcp_syncookies = 1:該參數與性能無關,用於解決TCP的SYN攻擊;
注意:滑動窗口的大小與套接字緩存區會在一定程度上影響並發連接的數目。每個TCP連接都會為維護TCP滑動窗口而消耗內存,這個窗口會根據服務器的處理速度收縮或擴張。 參數net.core.wmem_max = 12582912的設置,需要平衡物理內存的總大小、Nginx並發處理的最大連接數量而確定。當然,如果僅僅為了提供並發量使服務器不出現Out Of Memory問題而去降低滑動窗口大小,那么並不合適,因為滑動窗過小會影響大數據量的傳輸速度。net.core.rmem_default = 6291456、net.core.wmem_default = 6291456、 net.core.rmem_max = 12582912和net.core.wmem_max = 12582912這4個參數的設置需要根據我們的業務特性以及實際的硬件成本來綜合考慮。 Nginx並發處理的最大連接量:由nginx.conf中的work_processes和work_connections參數決定。
