Nginx
是一款自由的、開源的、高性能的HTTP服務器和反向代理服務器;同時也是一個IMAP
、POP3
、SMTP
代理服務器;Nginx
能夠做爲一個HTTP
服務器進行網站的發佈處理,另外Nginx
能夠做爲反向代理進行負載均衡的實現。
Nginx
如今幾乎是衆多大型網站的必用技術,大多數狀況下,咱們不須要去詳細的配置它,可是瞭解它在應用程序中所擔當的角色,以及如何解決這些問題是很是有必要的。下面就從基本概念開始介紹:javascript
代理是在服務器和客戶端之間架設的一層服務器,代理將接收客戶端的請求並將它轉發給服務器,而後將服務器的響應轉發給客戶端。css
不論是正向代理仍是反向代理,實現的都是上面的功能。html
位於客戶端和原始服務器(origin server)之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並制定目標(原始服務器),而後代理向原始服務器 轉交請求並將得到的內容返回給客戶端。
正向代理是爲客戶端服務的,客戶端能夠根據正向代理訪問到它自己沒法訪問到的服務器資源。前端
正向代理對客戶端是透明的,對服務端是非透明的,即服務端並不知道本身接收到的是來自代理的訪問仍是來自真實客戶端的訪問。
java
反向代理(
Reverse Proxy
)方式是值以代理服務器來接收鏈接請求,而後將請求轉發給內部網絡上的服務器,並將從服務器上獲得結構返回給請求鏈接的客戶端,此時代理服務器對外表現爲一個反向代理服務器。
反向代理是爲服務端服務的,反向代理能夠幫助服務器接收來自客戶端的請求,幫助服務器作請求的轉發、負載均衡等。nginx
反向代理對服務端是透明的,對客戶端是非透明的,即客戶端並不知道本身訪問的是代理服務器,而服務器知道反向代理在爲它服務。
web
下面是Nginx
配置文件的基本結構
json
events { } http { server { location path { ... } location path { ... } } server { ... } }
main
: Nginx的全局配置,對全局生效。events
: 配置影響Nginx服務器或與用戶的網絡鏈接。http
: 能夠嵌套多個server
,配置代理、緩存、日誌等絕大多數功能和第三方模塊的配置。server
: 配置虛擬主機的相關參數,一個http
中能夠有多個server
。location
: 配置請求的路由,以及各類頁面的處理狀況。upstream
: 配置後端服務器的具體地址,負載均衡不可或缺的部分。下面是Nginx
一些配置中的內置全局變量,你能夠在配置的任意位置使用它們。後端
變量名 | 功能 |
---|---|
$host |
請求信息中的Host ,若是請求中沒有Host 行,則等於設置的服務器名 |
$request_method |
客戶端請求類型,如GET 、POST 等 |
$remote_addr |
客戶端的IP 地址 |
$remote_port |
客戶端的端口 |
$args |
請求中的參數 |
$content_length |
請求頭中的Content-length 字段 |
$http_user_agent |
客戶端User-Agent 信息 |
$http_cookie |
客戶端的cookie 信息 |
$server_protocol |
請求使用的協議,如HTTP/1.0 、HTTP/1.1 |
$server_addr |
服務器地址 |
$server_name |
服務器名稱 |
$server_port |
服務器端口號 |
跨域指的是瀏覽器不能執行其餘網站的腳本。它是由瀏覽器的同源策略形成的,是瀏覽器對JavaScript
施加的安全限制。api
若是兩個頁面的協議、端口、域名都相同,則這兩個頁面同源。
URL | 結構 | 緣由 |
---|---|---|
http://clearlove.com/dir/a.html | 成功 | |
http://clearlove.com/dir2/b.html | 成功 | |
https://clearlove.com/dir/a.html | 失敗 | 不一樣協議(http和https) |
http://clearlove.com:81/dir/a.html | 失敗 | 不一樣端口(80和81) |
http://meiko.com/dir/a.html | 失敗 | 不一樣域名(clearlove和meiko) |
例如:
如今在fe.server.com
對dev.server.com
發起請求必定會出現跨域。
如今咱們只須要啓動一個Nginx服務器,將server_name
設置爲fe.server.com
,而後設置相應的location
以攔截前端須要跨域的請求,最後將請求代理回dev.server.com
。以下面的配置:
server { listen 80; server_name fe.server.com; location / { proxy_pass dev.server.com; } }
這樣能夠完美繞過瀏覽器的同源策略:fe.server.com
訪問Nginx
的fe.server.com
屬於同源訪問,而Nginx
對服務端轉發的請求不會觸發瀏覽器的同源策略。
error_page 500 501 502 503 504 506 /50x.html; location = /50x.html { #將根路徑改成存放html的路徑。 root /root/static/html; }
if ( $request_method !~ ^(GET|POST|HEAD)$ ) { return 403; }
能夠根據URL
、文件請求類型
等進行過濾。
gzip
是規定的三種標準HTTP
壓縮格式之一。目前絕大多數的網站都在使用gzip
傳輸 HTML
、CSS
、JavaScript
等資源文件。
對於文本文件,gzip
的效果很是明顯,開啓後傳輸所需流量大約會降至 1/4 ~ 1/3。
並非每一個瀏覽器都支持gzip
的,如何知道客戶端是否支持gzip
呢,請求頭中的Accept-Encoding
來標識對壓縮的支持。
啓用gzip
同時須要客戶端和服務端的支持,若是客戶端支持gzip
的解析,那麼只要服務端可以返回gzip
的文件就能夠啓用gzip
了,咱們能夠經過Nginx
的配置來讓服務端支持gzip
。下面的respone
中Content-Encoding: gzip
,指服務端開啓了gzip
的壓縮方式。
gzip on; gzip_http_version 1.1; gzip_comp_level 5; gzip_min_length 1000; gzip_types text/csv text/xml text/css text/plain text/javascript application/javascript application/x-javascript application/json application/xml;
gzip
模塊off
on
/ off
gZip
所需的HTTP
最低版本HTTP/1.1
這裏爲何默認版本不是1.0
呢?
HTTP
運行在TCP
鏈接之上,天然也有着跟TCP
同樣的三次握手、慢啓動等特性。
啓用持久鏈接狀況下,服務器發出響應後讓TCP
鏈接繼續打開着。同一對客戶/服務器之間的後續請求和響應能夠經過這個鏈接發送。
爲了儘量的提升 HTTP
性能,使用持久鏈接就顯得尤其重要了。
HTTP/1.1
默認支持TCP
持久鏈接,HTTP/1.0
也能夠經過顯式指定Connection: keep-alive
來啓用持久鏈接。對於TCP
持久鏈接上的HTTP
報文,客戶端須要一種機制來準確判斷結束位置,而在HTTP/1.0
中,這種機制只有Content-Length
。而在HTTP/1.1
中新增的Transfer-Encoding: chunked
所對應的分塊傳輸機制能夠完美解決這類問題。
Nginx
一樣有着配置chunked
的屬性chunked_transfer_encoding
,這個屬性是默認開啓的。
Nginx
在啓用了gZip
的狀況下,不會等文件gzip
完成再返回響應,而是邊壓縮邊響應,這樣能夠顯著提升 TTFB
(Time To First Byte,首字節時間,WEB性能優化重要指標)。這樣惟一的問題是,Nginx
開始返回響應時,它沒法知道將要傳輸的文件最終有多大,也就是沒法給出Content-Length
這個響應頭部。
因此,在HTTP1.0
中若是利用Nginx
啓用了gzip
,是沒法得到Content-Length
的,這致使HTTP1.0
中開啓持久連接和使用gzip
只能二選一,因此在這裏gzip_http_version
默認設置爲1.1
。
1
1-9
Content-Length
小於該值的請求將不會被壓縮。0
1000
以上MIME
類型)text/html
(默認不壓縮js/css
)upstream
指定後端服務器地址列表
upstream balanceServer { server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
在server
中攔截響應請求,並將請求轉發到upstream
中配置的服務器列表。
server { server_name fe.server.com; listen 80; location /api { proxy_pass http://balanceServer; } }
上面的配置只是指定了Nginx
須要轉發的服務端列表,並無指定分配策略。
默認狀況下采用的策略,將全部客戶端請求輪詢分配給服務端。這種策略是能夠正常工做的,可是若是其中某一臺服務器壓力太大,出現延遲,會影響全部分配在這臺服務器下的用戶。
upstream balanceServer { server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
將請求優先分配給壓力較小的服務器,它能夠平衡每一個隊列的長度,並避免向壓力大的服務器添加更多的請求。
upstream balanceServer { least_conn; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
依賴於Nginx Plus,優先分配給響應時間最短的服務器。
upstream balanceServer { fair; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
來自同一個IP
的請求永遠只分配一臺服務器,有效解決了動態網頁存在的session
共享問題。
upstream balanceServer { ip_hash; server 10.1.22.33:12345; server 10.1.22.34:12345; server 10.1.22.35:12345; }
Nginx實現負載均衡的策略中,每一臺服務器後面均可以攜帶的參數有:
down
: 當前服務器不參與負載均衡。weight
: 權重,值越大,服務器的負載量就越大。max_fails
: 容許請求失敗的次數,默認爲1。fail_timeout
: max_fails
次失敗後暫停的時間。backup
: 備份機,只有其它全部的非backup
機器down
或者忙時纔會請求backup
機器。以下面的配置是指:負載中有三臺服務器,當請求到達時,nginx按時間順序和權重把請求分配給三臺服務器處理,例若有100個請求,有30%是服務器33處理,有50%的請求是服務器34處理,有20%的請求是服務器35處理。
upstream balanceServer { server 10.1.22.33:12345 weight=30; server 10.1.22.34:12345 weight=50; server 10.1.22.35:12345 weight=20; }
以下面的配置是指:負載中有三臺服務器,服務器33的失敗超時時間爲60s,服務器34暫不參與負載,服務器35只用做備份機。
upstream balanceServer { server 10.1.22.33:12345 fail_timeout=60s; server 10.1.22.34:12345 down; server 10.1.22.35:12345 backup; }
location ~* \.(png|gif|jpg|jpeg)$ { root /root/static/; autoindex on; access_log off; expires 10h;# 設置過時時間爲10小時 }
匹配以png|gif|jpg|jpeg
爲結尾的請求,並將請求轉發到本地路徑,root
中指定的路徑即Nginx
本地路徑。同時也能夠進行一些緩存的設置。
常常會遇到但願網站讓某些特定用戶的羣體(好比只讓公司內網)訪問,或者控制某個url不讓人訪問。配置以下:
location / { deny 192.168.1.100; allow 192.168.1.10/200; allow 10.110.50.16; deny all; }
其實deny
和allow
是ngx_http_access_module
模塊(已內置)中的語法。採用的是從上到下匹配方式,匹配到就跳出再也不繼續匹配。
上述配置的意思就是,首先禁止192.168.1.100訪問,而後容許192.168.1.10-200 ip段內的訪問(排除192.168.1.100),同時容許10.110.50.16這個單獨ip的訪問,剩下未匹配到的所有禁止訪問。實際生產中,常常和ngx_http_geo_module
模塊(能夠更好地管理ip地址表,已內置)配合使用。
如今不少網站都存在PC站和H5站兩個站點,所以根據用戶的瀏覽環境自動切換站點是很常見的需求。
Nginx
能夠經過內置變量$http_user_agent
,獲取到請求客戶端的userAgent
,從而知道用戶處於移動端仍是PC,進而控制重定向到H5站仍是PC站。好比,PC端站點是mysite.com,H5端是mysite-H5.com。配置以下:
location / { # 移動、pc設備適配 if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') { set $mobile_request '1'; } if ($mobile_request = '1') { rewrite ^.+ http://mysite-H5.com; } }
上述只是經過一些簡單的應用,但願可以引發廣大前端童靴對Niginx
的興趣。事實上,Nginx
不只僅侷限於這些微小的工做,在實際生產中做用其實更加巨大。對於有志於「大前端」的童靴,瞭解和熟悉Nginx
絕對是必修技能之一。