前端必備-Nginx基礎及應用

Nginx是一款自由的、開源的、高性能的HTTP服務器和反向代理服務器;同時也是一個IMAPPOP3SMTP代理服務器;Nginx可以作爲一個HTTP服務器進行網站的發佈處理,另外Nginx可以作爲反向代理進行負載均衡的實現。

Nginx現在幾乎是衆多大型網站的必用技術,大多數情況下,我們不需要去詳細的配置它,但是瞭解它在應用程序中所擔當的角色,以及如何解決這些問題是非常有必要的。下面就從基本概念開始介紹:

正向代理與反向代理

代理是在服務器和客戶端之間架設的一層服務器,代理將接收客戶端的請求並將它轉發給服務器,然後將服務器的響應轉發給客戶端。

不管是正向代理還是反向代理,實現的都是上面的功能。

正向代理

位於客戶端和原始服務器(origin server)之間的服務器,爲了從原始服務器取得內容,客戶端向代理髮送一個請求並制定目標(原始服務器),然後代理向原始服務器轉交請求並將獲得的內容返回給客戶端。

正向代理是爲客戶端服務的,客戶端可以根據正向代理訪問到它本身無法訪問到的服務器資源。

正向代理客戶端是透明的,對服務端是非透明的,即服務端並不知道自己接收到的是來自代理的訪問還是來自真實客戶端的訪問。
正向代理

反向代理

反向代理(Reverse Proxy)方式是值以代理服務器來接收連接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到結構返回給請求連接的客戶端,此時代理服務器對外表現爲一個反向代理服務器。

反向代理爲服務端服務的,反向代理可以幫助服務器接收來自客戶端的請求,幫助服務器做請求的轉發、負載均衡等。

反向代理服務端是透明的,對客戶端是非透明的,即客戶端並不知道自己訪問的是代理服務器,而服務器知道反向代理在爲它服務。
反向代理

基本配置

配置結構

下面是Nginx配置文件的基本結構
Nginx配置結構

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 客戶端請求類型,如GETPOST
$remote_addr 客戶端的IP地址
$remote_port 客戶端的端口
$args 請求中的參數
$content_length 請求頭中的Content-length字段
$http_user_agent 客戶端User-Agent信息
$http_cookie 客戶端的cookie信息
$server_protocol 請求使用的協議,如HTTP/1.0HTTP/1.1
$server_addr 服務器地址
$server_name 服務器名稱
$server_port 服務器端口號

前端可以用Nginx做些什麼

解決跨域

跨域定義

跨域指的是瀏覽器不能執行其他網站的腳本。它是由瀏覽器的同源策略造成的,是瀏覽器對JavaScript施加的安全限制。

同源定義

如果兩個頁面的協議、端口、域名都相同,則這兩個頁面同源。

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)

Nginx解決跨域的原理

例如:

  • 前端server的域名爲:fe.server.com
  • 後端服務的域名爲:dev.server.com
    現在在fe.server.comdev.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訪問Nginxfe.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

gzip是規定的三種標準HTTP壓縮格式之一。目前絕大多數的網站都在使用gzip傳輸 HTMLCSSJavaScript 等資源文件。

對於文本文件,gzip的效果非常明顯,開啓後傳輸所需流量大約會降至 1/4 ~ 1/3。

並不是每個瀏覽器都支持gzip的,如何知道客戶端是否支持gzip呢,請求頭中的Accept-Encoding來標識對壓縮的支持。
圖片描述

啓用gzip同時需要客戶端和服務端的支持,如果客戶端支持gzip的解析,那麼只要服務端能夠返回gzip的文件就可以啓用gzip了,我們可以通過Nginx的配置來讓服務端支持gzip。下面的responeContent-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

  • 開啓或者關閉gzip模塊
  • 默認值爲off
  • 可配置爲on / off

gzip_http_version

  • 啓用 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

gzip_comp_level

  • 壓縮級別,級別越高壓縮率越大,當然壓縮時間也就越長(傳輸快但比較消耗cpu)。
  • 默認值: 1
  • 壓縮級別取值: 1-9

gzip_min_length

  • 設置允許壓縮的頁面最小字節數,Content-Length小於該值的請求將不會被壓縮。
  • 默認值: 0
  • 當設置的值較小時,壓縮後的長度可能比原文件大,建議設置1000以上

gzip_types

  • 要採用gzip壓縮的文件類型(MIME類型)
  • 默認值: text/html(默認不壓縮js/css)

負載均衡

Nginx如何實現負載均衡

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需要轉發的服務端列表,並沒有指定分配策略。

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綁定

來自同一個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;
}

其實denyallowngx_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與移動環境

現在很多網站都存在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絕對是必修技能之一。

其他

Nginx基本配置與參數說明

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章