前端想要了解的Nginx

快狗叫車前端團隊發表於2019-04-11

Nginx 是一個高效能的HTTP和反向代理伺服器,同時也是一個 IMAP/POP3/SMTP 代理伺服器。

常見場景:

  • 靜態資源伺服器
  • 動態匹配
  • 反向代理
  • Gzip 壓縮
  • 負載均衡

先來看下預設的Nginx配置,我將以此為基礎依次介紹Nginx的用法

Nginx 安裝目錄下的nginx.conf就是Nginx全域性的配置檔案,我們主要修改這裡的內容。nginx.conf.default作為配置檔案的備份。

# 設定工作程式的數量
worker_processes  1;
# 處理連線
events {
    # 設定連線數
    worker_connections  1024;
}

http {
    # 檔案擴充名查詢集合
    include       mime.types;
    # 當查詢不到對應型別的時候預設值
    default_type  application/octet-stream;

    # 日誌格式,定義別名為 main
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    # 指定日誌輸入目錄
    #access_log  logs/access.log  main;

    # 呼叫 sendfile 系統傳輸檔案
    sendfile        on;
    #tcp_nopush     on;

    # 客戶端與伺服器連線超時時間,超時自動斷開
    #keepalive_timeout  0;
    keepalive_timeout  65;

    # 開啟gizip 壓縮
    #gzip  on;

    # 虛擬主機
    server {
        listen       8080;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # 路由
        location / {
                root   html;
                index  index.html index.htm;
            }
    }

    # 引入其他的配置檔案
    include servers/*;
}
複製程式碼

搭建靜態站點

# 虛擬主機server塊
server {
    # 埠
    listen   8080;
    # 匹配請求中的host值
    server_name  localhost;
    
    # 監聽請求路徑
    location / {
        # 查詢目錄
        root /source;
        # 預設查詢
        index index.html index.htm;
    }
}
複製程式碼

這裡說明一下相關欄位

  • server 配置虛擬主機的相關引數,可以有多個
  • server_name 通過請求中的host值 找到對應的虛擬主機的配置
  • location 配置請求路由,處理相關頁面情況
  • root 查詢資源的路徑

配置完成後執行 nginx -t 看是否有錯誤,如果看到的是下面這種就是成功了

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
複製程式碼

然後執行nginx -s reload 更新Nginx配置檔案

這時候開啟瀏覽器 輸入 localhost:8080 應該就能看到你的頁面了

nginx -t 檢查配置檔案是否有語法錯誤
nginx -s reload 向主程式傳送訊號,重新載入配置檔案
nginx -s stop 快速關閉
nginx -s quit 等待工作程式處理完成後關閉

動態匹配(請求過濾)

通常在開發環境或者測試環境的時候呢我們修改了程式碼,因為瀏覽器快取,可能不會生效,需要手動清除快取,才能看到修改後的效果,這裡我們做一個配置讓瀏覽器不快取相關的資源。

location ~* \.(js|css|png|jpg|gif)$ {
    add_header Cache-Control no-store;
}
複製程式碼

~* \.(js|css|png|jpg|gif)$ 是匹配以相關檔案型別然後單獨處理。 add_header 是給請求的響應加上一個頭資訊Cache-Control no-store,告知瀏覽器禁用快取,每次都從伺服器獲取 效果如下:

Cache-Contro

匹配規則

通常的形式如下

location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
    [ configuration E ]
}
複製程式碼
  • = 表示精確匹配。只有請求的url路徑與後面的字串完全相等時,才會命中(優先順序最高)。
  • ^~ 表示如果該符號後面的字元是最佳匹配,採用該規則,不再進行後續的查詢。
  • ~ 表示該規則是使用正則定義的,區分大小寫。
  • ~* 表示該規則是使用正則定義的,不區分大小寫。

當然我們還可以通過狀態碼來過濾請求就像這樣

# 通過狀態碼,返回指定的錯誤頁面
error_page 500 502 503 504 /50x.html;
location = /50x.html {
    root /source/error_page;
}
複製程式碼

反向代理解決跨域

因為瀏覽器的同源策略,當前端域名與後端域名不一致的時候導致請求失敗。我們可以通過配置Nginx反向代理來解決。

location /api {   
    # 請求host傳給後端
    proxy_set_header Host $http_host;
    # 請求ip 傳給後端
    proxy_set_header X-Real-IP $remote_addr;
    # 請求協議傳給後端
    proxy_set_header X-Scheme $scheme;
    # 路徑重寫
    rewrite  /api/(.*)  /$1  break;
    # 代理伺服器
    proxy_pass http://localhost:9000;
}
複製程式碼
  • 攔截路徑/api, 可以通過正則匹配。
  • proxy_set_header 允許重新定義或新增欄位傳遞給代理伺服器的請求頭。
  • $http_host$remote_addr$scheme 為Nginx內建變數。
  • rewrite 根據rewrite後的請求URI,將路徑重寫,如:介面路徑為 /user, 我們可以請求 /api/user。(為什麼需要重寫uri?因為在使用Nginx做反向代理的時候,需要匹配到跨域的介面再做轉發,為了方便匹配,會人為的在原介面中新增一段路徑(或標示, 如例子中的api),因此需要在匹配之後、轉發之前把新增的那段去掉,因此需要rewrite。)
  • break 繼續本次請求後面的處理 ,停止匹配下面的location。需要注意的是與之類似的last執行過程則是停止當前這個請求,並根據rewrite匹配的規則重新發起一個請求,從上到下依次匹配location後面的規則。
  • proxy_pass 代理伺服器。

原理:Nginx攔截到相關匹配規則, Nginx再將請求轉發到http://localhost:9000,Nginx得到請求後再響應到前端,可以直接請求/api/user完成請求。

配置Gzip

開發過程中難免用到一些成熟的框架,或者外掛,這些外部的依賴,有時候體積比較大,導致頁面響應緩慢,我們可以用打包工具(webpack, rollup),將程式碼進行壓縮,以縮小程式碼體積。 開啟Nginx Gzip壓縮功能。需要注意的是 Gzip 壓縮功能需要瀏覽器跟伺服器都支援,即伺服器壓縮,瀏覽器解析。

  • 檢視瀏覽器支援情況,確定 請求頭 中的Accept-Encoding欄位

gzip瀏覽器支援

  • 確定瀏覽器支援,我們就可以在Nginx中配置
server {
    # 開啟gzip 壓縮
    gzip on;
    # 設定gzip所需的http協議最低版本 (HTTP/1.1, HTTP/1.0)
    gzip_http_version 1.1;
    # 設定壓縮級別,壓縮級別越高壓縮時間越長  (1-9)
    gzip_comp_level 4;
    # 設定壓縮的最小位元組數, 頁面Content-Length獲取
    gzip_min_length 1000;
    # 設定壓縮檔案的型別  (text/html)
    gzip_types text/plain application/javascript text/css;
}
複製程式碼
  • 檢視配置是否生效,檢視 響應頭 中的Content-Encoding欄位,值為 gzip

gzip生效

負載均衡

負載均衡是Nginx 比較常用的一個功能,可優化資源利用率,最大化吞吐量,減少延遲,確保容錯配置,將流量分配到多個後端伺服器。

Syntax:	upstream name { ... }
Default: —
Context: stream
複製程式碼

這裡舉出常用的幾種策略

  • 輪詢(預設),請求過來後,Nginx 隨機分配流量到任一伺服器
upstream backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
複製程式碼
  • weight=number 設定伺服器的權重,預設為1,權重大的會被優先分配
upstream backend {
    server 127.0.0.1:3000 weight=2;
    server 127.0.0.1:3001 weight=1;
}
複製程式碼
  • backup 標記為備份伺服器。當主伺服器不可用時,將傳遞與備份伺服器的連線。
upstream backend {
    server 127.0.0.1:3000 backup;
    server 127.0.0.1:3001;
}
複製程式碼
  • ip_hash 保持會話,保證同一客戶端始終訪問一臺伺服器。
upstream backend {
    ip_hash;  
    server 127.0.0.1:3000 backup;
    server 127.0.0.1:3001;
}
複製程式碼
  • least_conn 優先分配最少連線數的伺服器,避免伺服器超載請求過多。
upstream backend {
    least_conn;
    server 127.0.0.1:3000;
    server 127.0.0.1:3001;
}
複製程式碼

當我們需要代理一個叢集時候可以通過下面這種方式實現

http {

    upstream backend {
        server 127.0.0.1:3000;
        server 127.0.0.1:3001;
    }

    ...
    server {
        listen      9000;
        server_name localhost;
        
        location / {
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Scheme $scheme;
            
            proxy_pass backend; 
        }
    }
}
複製程式碼

最後

Nginx 的功能還有很多,這裡只介紹了幾個比較基礎、常用的,供大家學習和參考,快速入門,搭建出一套可用的環境。

參考連結

參考Nginx官方文件

相關文章