1. 概述
你們都知道Nginx有不少功能模塊,好比反向代理、緩存等,這篇文章總結下咱們這些年實際環境中那些有用的Nginx規則和模塊,大部分是用法的歸納及介紹,具體細節在實際配置時再自行google。javascript
2. 內置語法
先介紹Nginx默認已支持的內置功能,靠這些基本就知足大部分的web服務需求。php
2.1 proxy代理
proxy經常使用於兩類應用場景,一類是中轉,如異地科學的上網方式,另一類是到後端服務的負載均衡方案。css
用反向代理時候,須要特別注意裏面的域名默認是在nginx啓動時候就解析了,除非reload不然一直用的是當初解析的域名,也就是說不能動態解析。html
但這個問題是能夠經過別的模塊或者用內置字典變量方式來解決。前端
resolver 114.114.114.114; server { location / { set $servers github.com; proxy_pass http://$servers; } }
2.1.1 中轉
針對某個域名進行中轉:java
server { listen 172.16.10.1:80; server_name pypi.python.org; location ~ /simple { proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://pypi.python.org; } }
注意若是是先後端域名不同的話須要處理proxy_redirect的301跳轉之類的顯示,不然在跳轉時候會跳轉到proxy_pass的域名。python
另外能夠直接代理全部80端口的http流量:android
server { listen 80; server_name _; resolver 114.114.114.114; set $URL $host; location / { proxy_pass http://$URL; } }
若是是想代理https的站點也不是不可能,只是須要自行處理CA證書導入便可,並且通過https中轉的流量對nginx是透明的,也就是有證書的時候作竊聽和劫持的狀況。nginx
2.1.2 負載均衡
這是代理的另一個常見用法,經過upstream到多個後端,能夠經過weight來調節權重或者backup關鍵詞來指定備份用的後端,一般默認就能夠 了,或者能夠指定相似ip_hash這樣的方式來均衡,配置很簡單,先在http區域添加upstream定義:git
upstream backend { ip_hash; server backend1.example.com weight=5; server backend2.example.com weight=5;; }
而後在server裏面添加proxy_pass:
location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; }
作負載均衡的時候能夠智能識別後端服務器狀態,雖然能夠智能地proxy_next_upstream到另外的後端,但仍是會按期損失一些正常的「嘗試性」的鏈接,好比過了max_fails 次嘗試以後,休息fail_timeout時間,過了這個時間以後又會去嘗試,這個時候可使用第三方的upstream_check模塊來在後臺按期地自動探索,相似這樣:
check interval=3000 rise=2 fall=5 timeout=2000 type=http;
這樣替代用戶正常的鏈接來進行嘗試的方式進一步保障了高可用的特性。
還有就是在作前端代理的時候也是這樣的方式,直接proxy_pass到後端便可,好比CDN的場景。
2.2 防盜鏈
普通的防盜鏈是經過referer來作,好比:
location ~* \.(gif|jpg|png|bmp)$ { valid_referers none blocked *.example.com server_names ~\.google\. ~\.baidu\.; if ($invalid_referer) { return 403; } }
再精細一點的就是URL加密,針對一些用戶IP之類的變量生成一個加密URL一般是針對文件下載時候用到,能夠經過openresty來寫lua腳本或者是accesskey之類的模塊來實現。
2.3 變量
nginx裏面支持正則匹配和變量配置,默認的變量好比remote_addr、request_filename、query_string、server_name之類的,這些組合在一塊兒能夠作不少規則,或者還有日誌裏面status、http_cookie等。
還有在進行多域名配置時候能夠用通配符,好比:
server_name ~^(www\.)?(.+)$; root /data/web/$2;
這樣就實現了自動進行域名的目錄指派。
變量方面,好比配置變量a=1:
set $a 1;
下面這個案例配合if判斷來作有更大的用處。
2.4 if判斷
nginx裏面支持一些簡單的if判斷,可是沒有多重邏輯的語法,多個判斷條件用起來須要結合變量的方式來實現,好比容許ip地址爲10.10.61段和和192.168.100段的用戶訪問,其他的拒絕,返回405狀態碼:
set $err 0; if ( $remote_addr ~ 10.10.61.){ set $err 0; } if ( $remote_addr ~ 192.168.100.){ set $err 0; } if ( $err = 1){ return 405; }
這樣經過一個err變量比較巧妙實現了需求。
2.5 error_page
有用到後端proxy的地方須要加上這句話才能夠傳到狀態碼到nginx:
fastcgi_intercept_errors on;
具體配置通常是配置到具體的錯誤URL頁面,好比:
#返回具體狀態碼 error_page 404 403 /4xx.html #返回200狀態碼 error_page 404 403 =200 /error.html
或者採用callback的方式統一作處理:
error_page 404 403 = @fallback; location @fallback { proxy_pass http://backend; access_log /data/logs/404_error.log access; }
這樣在重定向時不會改變URL,而後把404頁面直接返回。
2.6 rewrite
rewrite作一些30一、302之類的跳轉,同時也能夠在CDN前端作「去問號」緩存的效果。
location /db.txt { rewrite (.*) $1? break; include proxy.conf; }
另外最多見的跳轉寫法:
rewrite ^/game/(.*) /$1;
把/game/test跳轉爲/test的效果,注意這樣是沒有狀態碼的,若是訪問正常就直接返回200狀態碼。
能夠在後面加個permanent參數,就變爲了301 Moved Permanently,或者添加redirect改成302跳轉。
同理,還能夠進行多個正則匹配進行URL重組,好比:
rewrite ^/download/(.*)/lastest/(.*)$ /file/$1?ver=$2 break;
2.7 日誌字段
想針對每一個鏈接進行日誌留檔,能夠在nginx日誌那裏配置好字段,好比記錄cookie之類的數據。
在log_format字段裏面加入$http_cookie變量便可。
另外post的數據能夠永久保留在文件裏面,好比用來作http的日誌備份,包括get和post的原始數據,把這個值開啓便可:
client_body_in_file_only on;
而後post的數據就會保存在nginx/client_body_temp文件夾裏面。
2.8 internal關鍵詞
這個關鍵詞不多見,但有時候是頗有用的,好比在有不少規則時候,忽然須要針對某個目錄轉爲nginx內部處理。
location ^~ /upload/down/ { alias /data/web/dts/dtsfile/down/; internal; }
2.9 try_files
字面意思是嘗試,後面能夠接多個目錄或者文件,好比kohana框架:
try_files $uri /index.php?$query_string;
先看是否有URL這個文件,沒有的話再調用index.php來處理,或者支持狀態碼處理:
try_files /foo /bar/ =404;
沒有這兩個文件的話返回404狀態。
2.10 auth認證
能夠作簡單的用戶登陸認證方式,其中的passwd_file得經過apache的htpasswd命令來生成。
auth_basic "Restricted"; auth_basic_user_file passwd_file;
認證經過以後每次訪問會在頭部添加Authorization字段包含用戶名密碼的base64加密密文給服務端。
2.11 gzip
普通的線上web站點gzip壓縮是必需要開的,壓縮一些文本類型的文件再返回給用戶。
注意必須手動指定全須要壓縮的類型,好比css、js之類的,線上配置以下:
gzip on; gzip_min_length 2048; gzip_buffers 4 16k; gzip_vary on; gzip_http_version 1.1; gzip_types text/plain text/css text/xml application/xml application/javascript application/x-javascript ;
2.12 mime配置
好久之前基本是忽略這個配置,但手遊流行以後就發現異常了,須要讓手機瀏覽器知道返回的apk後綴是什麼類型,不然相似IE瀏覽器會以zip後綴返回,須要加上:
application/vnd.android.package-archive apk; application/iphone pxl ipa;
2.13 限速
限速包括限制請求的併發數和請求的下載速度。
簡單的限制某個線程的下載速度就直接加上一句話就能夠了:
limit_rate 1024k;
要限制某個IP的併發數之類的就須要用ngx_http_limit_req_module和ngx_http_limit_conn_module模塊了,不過是默認就編譯好的。
好比使用一個 10M 大小的狀態緩存區,針對每一個IP每秒只接受20次的請求:
limit_req_zone $binary_remote_addr zone=NAME:10m rate=20r/s;
2.14 location匹配
location匹配有多種方式,常見的好比
location = / location / location ^~ /test{
是有優先級的,直接 」=」 的優先級是最高的,通常就用」~」這個符號來匹配php就行了,不過是區分了大小寫的:
location ~ .*\.php$
2.15 文件緩存
返回給用戶的文件通常都配置了過時時間,讓瀏覽器緩存起來。
好比緩存14天:
expires 14d;
針對某些特殊的文件就須要location匹配以後進行禁止緩存配置:
add_header Cache-Control no-cache; add_header Cache-Control no-store; expires off;
2.16 緩存文件
nginx能夠做爲ATS這樣的緩存服務器來緩存文件,配置也比較簡單,不過咱們不多用,除非一些特殊的場合,參考配置:
3. 內置模塊#先在全局下面定義好緩存存放的目錄 proxy_cache_path /data/cache/ levels=1:2 keys_zone=cache_one:10m inactive=7d max_size=10g; proxy_temp_path /data/cache/proxy_temp_path; proxy_cache_key $host$uri$is_args$args; #而後在server裏面的location匹配好目的文件,加入下一段便可 proxy_cache cache_one; proxy_cache_valid 200 304 24h; proxy_cache_valid any 10m; proxy_pass https://$host; proxy_cache_key $host$uri$is_args$args; add_header Nginx-Cache "$upstream_cache_status";
3. 內置模塊
nginx含有大量的模塊能夠支持多種複雜的需求,好比源碼目錄src/http/modules裏面就有不少c模塊的代碼,或者直接經過./configure –help|grep module來查看有哪些內置模塊,編譯時候直接加上就能夠了。
除了nginx內置的模塊,網絡上還有不少第三方的模塊,能夠經過編譯時候加參數–add-module=PATH指定模塊源碼來編譯。
下面介紹一些咱們線上用過並且比較讚的內置模塊。
3.1 stream
端口轉發的模塊,從nginx1.9版本纔開始支持,包含tcp和udp的支持,和IPTABLES相比這個雖然是應用層,會監聽端口,可是配置起來很方便,比IPTABLES靈活,在tcp模塊下面添加相似vhost的server就能夠了,方便自動化管理,參考配置:
server { listen PORT; proxy_pass IP:PORT; access_log /data/logs/tcp/PORT.log; }
3.2 http_realip_module
nginx反向代理以後,如何讓後端web直接獲取到的IP不是反向代理的iP,而是直接獲取到用戶的真實IP呢,就須要這個模塊了,不須要代碼那裏再作相似X-Real-IP的變量特殊判斷。
3.3 http_slice_module
在作CDN時候能夠用到,讓一個大文件分片,分紅多個小文件經過206斷點續傳到後端,而後再組合起來,避免大文件直接回源致使多副本和屢次回源的問題。
3.4 http_secure_link_module
前面說到的防盜鏈能夠用這個來作,可是這個通常是針對那種文件下載時候用到的,好比從網頁下載時候,服務端生成一個加密URL給用戶,而後這個URL有過時時間之類的,避免此URL被屢次分享出去,不過普通的素材加載仍是用普通的防盜鏈便可。
3.5 http_sub_module
替換響應給用戶的內容,相對於sed以後再返回,好比能夠在須要臨時全局修改網站背景或者title時候能夠一次性處理好。
4. 擴展項目
簡單介紹下大名鼎鼎的兩個基於nginx的擴展項目,也是咱們線上有不少地方用到的。
4.1 openresty
集成lua腳本,幾乎能夠完成任何普通web相關的需求。
好比URL加密進行防劫持和防盜鏈,服務端動態生成一串aes加密的URL給CDN,CDN的openresty解密以後用普通的URL轉發到後端,而後再返回給用戶正確的內容。
4.2 tengine
淘寶的nginx修改版,實現了不少nginx的收費功能或者是特殊功能,好比動態加載、concat合併請求,動態解析等。
咱們python開發的後臺基本都是用的這個版本,主要是利用了concat的合併素材的功能。
5. 結語
Nginx是個很是實用軟件,部分功能已經超越了普通的web服務定位,同時它具有開源、輕量、自動化等特性,能有效解決實際工做中不少特殊場景的需求。