企業級Nginx服務基礎到架構優化詳解--25條 2016-08-18 00:57:26
1、隱藏nginx header版本號
2、更改源碼隱藏軟件名稱
3、更改nginx默認用戶及用戶組
4、配置nginx worker進程個數
5、根據CPU核數進行nginx進程優化
6、nginx事件處理模型優化
7、調整Nginx worker單個進程允許的客戶端最大連接數
8、配置Nginx worker進程最大打開文件數
9、開啓高效的文件傳輸模式
10、設置連接超時時間
11、上傳文件大小設置(動態應用)
12、fastcgi調優(配合PHP引擎動態服務)
13、配置nginx gzip壓縮功能
14、配置Nginx expires緩存功能
15、Nginx日誌相關優化與安全
16、Nginx站點目錄及文件URL訪問控制(防止惡意解析)
17、防止惡意解析訪問企業網站
18、Nginx圖片及目錄防盜鏈
19、Nginx錯誤頁面的優雅顯示
20、Nginx防爬蟲優化
21 、限制HTTP請求方法
22、防DOS***
23、使用CDN爲網站內容加速
24、Nginx程序架構優化
25、使用普通用戶啓動Nginx(監牢模式)
查看版本號
1 2 3 4 5 6 7 8 | [root@db02 ~] # curl -I http://www.lichengbing.cn HTTP /1 .1 200 OK Server: nginx /1 .6.3 Date: Tue, 16 Aug 2016 14:39:48 GMT Content-Type: text /html ; charset=UTF-8 Connection: keep-alive X-Powered-By: PHP /5 .5.32 Link: <http: //www .lichengbing.cn /wp-json/ >; rel= "https://api.w.org/" |
編譯nginx.conf配置文件,添加server_tokens off參數
1 2 3 4 5 6 7 8 | http { ... server_tokens off; #控制http response header內的服務版本信息的顯示,以及錯誤信息中web服務版本信息 ... } [root@db02 ~] # curl -I http://www.lichengbing.cn HTTP /1 .1 200 OK Server: nginx #版本隱藏 |
修改3個nginx源碼文件
第一個nginx-1.6.3/src/core/nginx.h文件
1 2 3 4 5 6 | [root@lichengbing nginx-1.6.3] # cd ~/tools/nginx-1.6.3 [root@lichengbing nginx-1.6.3] # sed -n '13,17p' src/core/nginx.h #define NGINX_VERSION "1.6.3" #改成你想要的版本號,如2.2.5 #define NGINX_VER "Nginx/" NGINX_VERSION #你想改成的軟件名稱,如Apache #define NGINX_VAR "NGINX" #可以改成OWS等 #define NGX_OLDPID_EXT ".oldbin" |
第二個
1 | [root@lichengbing nginx-1.6.3] # sed -i 's#Server: nginx#Server: OWS#g' src/http/ngx_http_header_filter_module.c |
第三個ngx_http_special_response.c是否對外展示敏感信息
1 2 3 4 5 6 7 8 9 | [root@lichengbing nginx-1.6.3] # sed -n '21,30p' src/http/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 |
修改爲如下
1 2 3 4 5 6 7 8 9 | [root@lichengbing nginx-1.6.3] # sed -n '21,30p' src/http/ngx_http_special_response.c static u_char ngx_http_error_full_tail[] = "<hr><center>" NGINX_VER " (http://www.lichengbing.cn)</center>" CRLF "</body>" CRLF "</html>" CRLF ; static u_char ngx_http_error_tail[] = "<hr><center>OWS</center>" CRLF "</body>" CRLF |
重新編譯安裝nginx,重啓服務
1 2 3 4 5 6 7 8 9 10 | [root@lichengbing ~] # grep '#user' /application/nginx/conf/nginx.conf.default #user nobody; #系統默認的用戶爲nobody [root@lichengbing ~] # useradd www -s /sbin/nologin -M #建立用戶www user www www; #nginx.conf 中配置用戶 也可以在編譯時加入用戶和用戶組,如 --user=www --group=www --with-http_ssl_module --with-http_stub_status_module --prefix= /application/nginx-1 .6.3/ [root@lichengbing ~] # ps -ef|grep nginx|grep -v grep root 1386 1 0 Jul21 ? 00:00:00 nginx: master process /application/nginx/sbin/nginx www 24732 1386 0 23:19 ? 00:00:00 nginx: worker process #此時worker process進程就是使用的www用戶權限,當然也可以使master降權運行 |
1 2 3 4 5 6 7 | worker_processes 8; #最好爲服務器CPU的邏輯核心數 [root@netmonitor ~] # grep "physical id" /proc/cpuinfo|sort|uniq|wc -l #物理核數 2 [root@netmonitor ~] # grep "cpu cores" /proc/cpuinfo|uniq #單核心數 cpu cores : 4 [root@netmonitor ~] # grep "processor" /proc/cpuinfo|wc -l #邏輯核心數 8 |
親和力參數(Nginx服務可能會發生只在同一顆CPU上起作用的情況)
1 2 3 | worker_processes 8; worker_cpu_affinity 001 0010 0100 1000; #數字代表1、2、3、4的掩碼,平均分攤進程壓力 worker_cpu_affinity 00000001 00000010... #8核心寫法 |
防止進程只在一個核心上運行也可以使用 taskset 命令
1 | taskset -c 1,2,3 /application/nginx/sbin/nginx start |
nginx的連接處理機制在不同的操作系統中會採用不同的I/O模型:Linux上使用epoll、BSD上面用kqueue、Solaris中使用/dev/poll、windows中使用icop.
1 2 3 | events { use epoll; #nginx官方建議,可以不指定事件處理模型,Nginx會自動選擇最佳的事件處理模型 } |
7、調整Nginx worker單個進程允許的客戶端最大連接數
1 2 3 4 5 6 7 | worker_processes 8; events { worker_connections 1024; } #最大連接數Max_client = worker_processes * worker_connections #進程的最大連接數收Linux系統進程的最大打開文件數限制,在執行操作系統命令“ulimit -HSn 65535”後,才能生效 #連接數並不是越大越好,要在系統性能能接受的範圍內 |
1 2 3 | events { worker_rlimit_nofile 65535; #該值可設置爲系統優化後的ulimit -HSn的結果 } |
1 2 3 4 | http { sendfile on; #開啓文件的高效傳輸模式 } #同時將tcp_nopush和tcp_nodelay兩個指令設置爲on,減少網絡傳輸包數量、防止網絡及磁盤的I/O阻塞,提升Nginx效率 |
1 2 3 4 5 6 7 8 | http { keepalive_timeout 65; #設置客戶端連接保持會話的超時時間 tcp_nodelay on; #激活tcp_nodelay,提高I/O性能,在包含keepalive參數時纔有效 client_header_timeout 15; #讀取客戶端請求頭數據超時時間,超時則返回“Request time out(408)” clietn_body_timeout 15; #讀取客戶端請求主體超時時間 send_timeout 15; #指定客戶端響應時間 } #將無用的連接儘快設置爲超時,可以保護服務器的系統資源(CPU、內存、磁盤) |
1 2 3 | http { client_max_body_size 10m; #具體數字要根據業務需求決定 } |
fastcgi作爲靜態服務和動態服務之間的傳接口,也有cache和buffer緩存和緩衝區
1 2 3 4 5 6 7 8 9 10 | http { fastcgi_connect_timeout 240; #連接到後端fastcgi的超時時間 fastcgi_send_timeout 240; #已經和fastcgi建立連接後多久不傳送數據,就會被斷開 fastcgi_read_timeout 240; #接收fastcgi應答的超時時間 fastcgi_buffer_size 64k; #指定讀取fastcgi應答第一部分需要多大的緩衝區,可以設置爲gastcgi_buffers選項指定的緩衝區大小 fastcgi_busy_buffers_size 128k; #繁忙時的buffer,可以是fastcgi_buffer的兩倍 fastcgi_temp_path /data/ngx_fcgi_tmp ; 在寫入fastcgi_temp_path時將用多大的數據庫,默認是fastcgi_buffer的兩倍,如果太小,可能會報502 Bad GateWay fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_s ize=40g; #指定相關參數配比 } |
在server標籤中配合設置相關參數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | server { 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; #表示開啓緩存併爲其指定一個名稱,開啓緩存非常有用,可以有效降低cpu的負載,並且防止502的發生,但是也可能會帶來其他問題 fastcgi_cache_valid 200 302 1h; #將對應的應答碼緩存時間 fastcgi_cache_valid 301 1d; #將301緩存1天 fastcgi_cache_valid any 1m; #將其他應答緩存1分鐘 fastcgi_cache_min_uses 1; #請求數量 fastcgi_cache_use_stale error timeout invalid_header http_500; #錯誤判斷 } } |
###(重要!!!)幾k字節的壓縮比在大數據量的衝擊下也可以節省不少的流量,網站內容傳輸速度更快,爲用戶帶來更好的瀏覽體驗
Nginx gzip壓縮模塊提供了壓縮文件內容的功能,用戶請求的內容在發送到用戶客戶端之前,Nginx服務器會根據一些具體的策略實施壓縮,到客戶端後由瀏覽器解壓
Nginx 依賴ngx_http_gzip_module模塊
Apache 使用mod_deflate壓縮功能
1 2 3 4 5 6 7 8 9 | http { gzip on; #開啓壓縮功能 gzip_min_length 1k; #允許壓縮的最小頁面字節數,從header頭的Content-Length中獲取,不管頁面多大都進行壓縮,建議設置成大於1K,如果小於1K可能會越壓縮越大 gzip_http_version 1.1; #壓縮版本,默認爲1.1,目前大部分瀏覽器都支持壓縮 gzip_buffers 4 32k; #壓縮緩衝大小,允許申請4個單位爲32K的內存作爲流緩存 gzip_comp_level 9; #壓縮比例,1最小,9最大,傳輸速度最快,但是比較消耗資源 gzip_types text /css text /xml application /javascript ; #指定壓縮的內容類型 gzip_vary on; #vary header支持,讓前端的緩存服務器繼續緩存傳輸該壓縮頁面,而不提前解壓 } |
(重要!!!)
在網站的開發和運營過程中,視頻、圖片、CSS、JS等網站元素的更改機會較少,我們可以將這些更改頻率較少的內容緩存在用戶本地,用戶在第二次訪問網站時就不用繼續去服務器下載了,節省流量,加快訪問速度
1 2 3 4 5 6 7 8 9 10 | server { location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ #指定緩存文件的類型 { expires 3650d; #指定緩存時間 } location ~ .*\.(js|css)?$ { expires 3d; } } |
expires緩存的缺點就是在網站更新相關數據後,用戶如果不清理緩存看到的就會一直是過期的數據,爲了解決這個問題,可以1、縮短緩存時間,比如百度的首頁圖片緩存時間爲一天;2、服務後臺更改圖片名稱,這樣就相當於是一個新的頁面內容,用戶會重新下載 3、相關的CSS、JS推送到CDN
1)每天進行日誌切割,備份
1 2 3 4 5 | #!/bin/sh cd /application/nginx/logs/ mv www_access.log www.access_$( date +%F -d -1day).log mv blog_access.log blog.access_$( date +%F -d -1day).log /application/nginx/sbin/nginx -s reload |
1 2 3 | cat >> /var/spool/cron/root <<EOF 00 00 * * * /bin/sh /server/scripts/cut_nginx_log .sh > /dev/null 2>&1 EOF |
2)不記錄不需要的訪問日誌
對於健康檢查或者某些圖片、JS、CSS日誌,一般不需要記錄日誌,因爲在統計PV時是按照頁面計算的,而且寫入頻繁會消耗IO,降低服務器性能
1 2 3 | location ~ .*\.(js|jpg|JPG|jpeg|JPEG|css|bmp|gif|GIF)$ { access_log off; } |
3)訪問日誌的權限設置
1 2 | chown -R root.root /application/nginx/logs chmod -R 700 /application/logs |
16、Nginx站點目錄及文件URL訪問控制(防止惡意解析)
1)根據擴展名限制程序或者文件被訪問
資源文件夾如用戶上傳的頭像,防止惡意上傳腳本病毒文件被解析執行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | server { location ~ ^ /p_w_picpaths/ .*\.(php|php5|sh|pl|py)$ { #指定目錄限制訪問 deny all; } location ~ ^ /static/ .*\.(php|php5|sh|pl|py)$ { deny all; } location ~ ^ /data/ .*\.(php|php5|sh|pl|py)$ { deny all; } location ~ .*\.(php|php5)?$ { #必須配置在解析之前 root html /www ; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } } |
2)禁止訪問目錄並返回指定HTTP代碼
1 2 3 | server { location /admin/ { return 404; } } |
3)限制網站來源IP
1 2 3 4 5 6 7 | server { location ~ ^ /admin/ { allow 202.111.12.211; #allow 192.168.1.0/24; #也可以限制IP段 deny all; } } |
企業問題案列:Nginx做方向代理的時候可以限制客戶端IP嗎?
方法一:用if來控制
1 2 3 4 5 6 | if ( $remotea_addr = 10.0.0.110 ) { return 403; } if ( $remotea_addr = 10.0.0.111 ) { set $allow_access_root 'true' ; } |
方法二:利用deny和allow
1 2 3 4 5 6 | location / { root html /blog ; index index.php index.html index.html; deny 10.0.0.7; allow all; } |
方法一
1 2 3 4 5 | server { listen 80 default_server; server_name _; return 501; } |
方法二
1 2 3 4 5 | server { listen 80 default_server; server_name _; rewrite ^(.*) http: //www .lichengbing.cn$1 permanent; } |
方法三
1 2 3 4 | server { if ($host !~ ^www/.lichengbing/.com$) { rewrite ^(.*) http: //www .lichengbing.cn$1 permanent; } |
網站圖片被盜鏈最直接的影響就是網絡帶寬佔用加大了,寬帶費用變高了,網絡流量忽高忽低,Zabbix頻繁告警
由於購買了CDN加速,流量高了好幾個G,瞬間損失好幾萬...
利用referer防盜鏈
1 2 3 4 5 6 7 | location ~.* \.(jpg|gif|png|swf|flv|wma|wmv|asf|mp3|mmf|zip|rar)$ { valid_referers none blocked *.lichengbing.cn lichengbing.cn; if ($invalid_referer) { rewrite ^/ http: //www .lichengbing.cn /img/nolink .jpg } } #或者也可以使用NginxHttpAccessKeyModule實現防盜鏈 |
1 2 3 | server { error_page 403 /403 .html; #當出現403錯誤時,會跳轉到403.html頁面 } |
robots.txt機器人協議
網絡爬蟲排除標準,告訴搜索引擎哪些目錄可以抓取,哪些禁止抓取
禁止下載協議代理
1 2 3 | if ($http_user_agent ~* LWP::Simple|BBBike|wget) { return 403; } |
防止N多爬蟲代理訪問網站
1 2 3 4 | 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; } |
禁止不同瀏覽器訪問
1 2 3 4 | if ($http_user_agent ~* “Firefox|MSIE”) { rewrite ^(.*) http: //blog .etiantian.org/$1 permanent } |
1 2 3 | if ($request_method !~ ^(GET|HEAD|POST)$ ) { return 501; } |
只允許GET等,允許DELETE、SEARCH等
爲防止***通過上傳服務器執行***,也可以在上傳服務器上做限制HTTP的GET
1 2 3 | if ($request_method ~* ^(GET)$ ) { return 501; } |
使用limit_conn_zone進行控制,控制單個IP或域名的訪問次數,限制連續訪問
1 2 3 4 5 6 7 | limit_conn_zone $binary_remote_addr zone=perip:10m; limit_conn_zone $server_remote_addr zone=perserver:10m; server { limit_conn perip 10; limit_conn perserver 100; } #還可以使用limit_req_zone進行控制,控制單個IP的訪問速率 |
全國或全球的內容分佈式緩存集羣,其實質通過智能DNS判斷用戶的來源地域及上網線路,爲用戶選擇一個最接近用戶地域,以及和用戶上網線路相同的服務器節點,提升用戶瀏覽網站的體驗
要加速的業務數據應該存在獨立的域名,然後刪除A記錄解析,使用CNAME解析
解耦,一堆程序代碼按照業務用途分開,然後提供服務,例如:註冊登錄、上傳、下載、瀏覽列表、商品內容、訂單支付等都應該是獨立的程序服務,只不過在客戶端看來是一個整體而已,小公司最起碼要做到的解耦是
01網頁頁面服務
02圖片附件及下載服務
03上傳圖片服務
降權思想,Nginx的Master進程使用的是root用戶,worker進程使用的是nginx指定的普通用戶,用root跑nginx的Master進程有兩大問題:1是最小化權限分配遇到問題;2、網站一旦有漏洞,很容易丟掉root權限
降權執行的好處:
1、創建普通用戶inca,用inca跑Nginx服務,開發運維都使用普通帳號,只要和inca同組,照樣可以管理nginx,還解決了root權限太大問題
2、職責分明,相關賬號負責維護程序和日誌,出問題負首要責任