Nginx 初探

Reaper622發表於2019-10-07

Nginx 初探

Nginx 是一個非同步框架的 Web 伺服器,也可以作為反向代理,負載均衡器和 HTTP 快取。

Nginx 的特點

  • 更快 : 單次請求相應會更快,高併發環境有更好的響應速度。
  • 高擴充套件性: Nginx 基於模組化設計,低耦合度,具有良好的可擴充套件性。
  • 高可靠性:每個 worker程式相對獨立,master 程式在一個 worker 程式出錯時可以快速拉起新的 worker 子程式提供服務。(反向代理)。
  • 低記憶體消耗:一般情況下,10000個非活躍的 HTTP Keep-Alive 連線在 Nginx 中僅消耗 2.5MB 的記憶體。 Nginx 傷的併發連線上限取決於記憶體大小。
  • 熱部署:master程式與worker程式分離,使得 Nginx 支援熱部署,可在不間斷服務的前提下,升級 Nginx 的可執行檔案。

Nginx 的反向代理功能

網際網路時代,網路應用基本都屬於CS結構,即 client 端與 server 端。代理就是在 client 與 server 之間增加了一層用於特定功能的伺服器(代理伺服器)。

正向代理

正向代理,即是一個位於客戶端與原始伺服器之間的伺服器,為了獲取原始伺服器的內容,客戶端會想代理髮送一個請求並指定目標,然後代理向原始伺服器轉交請求並將獲得的內容返回給客戶端。一個簡單的例子,我們有時會使用的歪皮恩(梯子)就是一個正向代理,它會把我們訪問牆外的一些網頁請求,代理到一個可以訪問此網站的代理伺服器上,代理伺服器去請求網頁內容後,再轉發給我們。

  • 正向代理是為客戶端服務的,客戶端可以根據正向代理訪問到它本來訪問不到的資源。
  • 正向代理對客戶端是透明的,但對於服務端不是透明的,服務端無法判斷自己是獲取到客戶端的請求還是代理伺服器的請求。

ugPz1f.png

​ ——使用 @ConardLi 的一幅圖做直觀的展示

反向代理

反向代理,即以代理伺服器來接受網路上的請求,然後把請求轉發給內部網路的伺服器(可以不止一臺),並將伺服器上的結果返回給網路上的客戶端。

  • **反向代理 ** 是為服務端服務的,反向代理幫助伺服器接受並轉發客戶端的請求,從而幫助伺服器完成負載均衡等功能。
  • 反向代理 對服務端透明,對我們卻不透明,我們無法直接通過請求來訪問伺服器,必須要先通過代理伺服器,這也在一定程度上保護了內容伺服器的安全。
  • 反向代理 可以把收到的客戶端請求均勻地分配到伺服器叢集中來實現負載均衡,同時 Nginx 擁有伺服器心跳檢查功能,如果有一臺伺服器異常,那麼代理進來的請求不會再傳送到該伺服器上,而是直到該伺服器恢復正常才會繼續向這個伺服器進行請求分發,這也大大保證了服務的穩定性。

在安裝 Nginx 時,強烈推薦使用原始碼編譯的模式安裝,這樣便於後期模組的新增,同時由於 Nginx 後續會升級版本,所以可以使用配置和程式分離的模式安裝。具體規則詳見:Nginx 目錄建議

Nginx的一些變數

涉及較多,較全的變數可以去Nginx變數檢視,這裡只說一些常用的。

  • 服務端相關
    • $server_port 伺服器埠號
    • $server_addr 伺服器地址 (ip地址)
    • $server_name 伺服器名稱 (一般也為ip地址)
    • $status HTTP的狀態碼
  • 客戶端相關
    • $http_accept 瀏覽器支援的 MIME 型別
    • $http_accept 瀏覽器支援的壓縮編碼
    • $http_cache_control 瀏覽器快取
    • $http_user_agent 使用者裝置標識
  • 連結相關
    • $uri 請求中當前的URI 可不同於​request_uri,可通過內部重定向。
    • $request_uri 客戶端請求引數的原始 URI
    • $request_method 請求方法
    • $args 請求引數,即uri後面的引數部分

Nginx 的一些正則匹配規則

~ 區分大小寫匹配 | ~*不區分大小寫匹配

!~ 區分大小寫不匹配 | !~* 不區分大小寫不匹配

-d 與 !-d 用來判斷是否存在目錄

-f 與 !-f 用來判斷是否存在檔案

-e 與 !-e 用來判斷是否存在檔案或者目錄

-x 和 !-x 用來判斷檔案是否可執行

Nginx 的基本配置

一個基本的 Nginx 的配置為 (可以去檢視安裝後的 nginx.conf 檔案)

events { 
	# 配置影響 Nginx 伺服器與使用者的網路連線
}

http # 可巢狀多個 server 配置代理,快取,日誌定義等絕大多數功能與第三方模組配置。
{
    server # 配置虛擬主機的相關引數
    { 	# location 配置請求的路由,以及頁面的各種情況
        location path 
        {
            ...
        }
        location path
        {
            ...
        }
     }

    server # 一個http中可以有多個 server
    {
        ...
    }

}

複製程式碼

Nginx 的一些常用功能

解決跨域

跨域問題是我們經常遇到也是我們有點偏為頭疼的一個問題,但當我們使用 Nginx 時,我們可以利用代理轉發的特性幫助我們解決跨域問題。

例如,我們的網站為content.app.com,而服務端為 server.app.com,給我們的介面地址為/api此時我們通過啟動一個Nginx伺服器攔截前端跨域的請求,通過代理來訪問server.app.com

server {
  #監聽80埠
	listen 80; 
	server_name content.app.com;
	location /api {
		proxy_pass server.app.com;
	}
}
複製程式碼

即我們請求content.app.com/api會被代理伺服器轉發給server.app.com,而我們在 content.app.com訪問的就是代理伺服器的 content.app.com,屬於同源訪問,就不存在跨域的現象了。

狀態碼與錯誤配置

server {
		# 訪問私密檔案時報 403 錯誤
		location /secret.js {
			return 403;
		}
  
  	# 指定不同狀態碼轉到特別的檔案
  	error_page 404 /404.html;
    error_page 500 501 502 503 /error.html;
  	# 此時的響應碼為 400
  	error_page 404 = 400 /400.html; 
}
複製程式碼

注意:error_page 後如果加了 = 號,則響應為制定的響應碼,預設為 200 ,不加等號則為原錯誤的狀態碼。

配置HTTPS 服務

配置 HTTPS 我們需要在編譯階段讓 Nginx 開啟 http_ssl_module 模組,我們可以使用 nginx -V命令來檢視

若結果為 TLS SNI support enabled 則證明已經開啟。

之後我們需要去下載證書,一般證書下載解壓後會有多種格式,使用 Nginx 格式,即 crtkey即可。

# 配置 HTTPS

# 配置個http的站點,用來做重定向,當然如果你不需要把 HTTP->HTTPS 可以把這個配置刪了
server {
    listen       80;

    # 配置域名
    server_name www.safe.com safe.com;

    # 新增 STS, 並讓所有子域支援, 開啟需慎重
    add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';

    # 配置讓這些 HTTP 的訪問全部 301 重定向到 HTTPS 的,
    rewrite ^(.*) https://www.safe.com$1 permanent;
    # rewrite 後若為 break,即url重寫後直接使用當前資源,不再執行location中其他語句,url位址列不變。
    # rewrite 後若為 last,即url重寫後,馬上發起一個新的請求,再次進入server 快,完成location匹配,url位址列不變
    # rewrite 後若為 redirect,則返回302臨時重定向,位址列url顯示重定向後的,爬蟲不更新url
    # rewrite 後若為 permanent,則進行301永久重定向,位址列顯示重定向後的url,爬蟲更新url。
}

# 配置 HTTPS
server {
    # 配置域名
    server_name www.safe.com safe.com;

    # https預設埠
    listen 443;

    # 新增STS, 並讓所有子域支援, 開啟需慎重
    add_header strict-transport-security 'max-age=31536000; includeSubDomains; preload';

    # https配置
    ssl on;
    ssl_certificate /ssl/ssl.crt;
    ssl_certificate_key /ssl/ssl.key;

    # 其他按正常配置處理即可...
}
複製程式碼

適配PC與移動端環境

雖然現在很多跨端應用於自適應功能日趨完善,但還是有很多網站是同時存在PC於H5兩個站點,因此根據使用者的裝置來切換站點也是一項常見的需求。這時我們需要使用到內建變數http_user_agent來獲取到使用者的裝置資訊,從而根據裝置來返回不同的節點。

location / {
	# 移動端裝置匹配
  if ($http_user_agent ~* '(Android|webOS|iPhone|iPad|BlackBerry)') {
    set $mobile_request '1';
  }
  if ($mobile_request = '1') {
    rewrite ^.+ https://mobile.com 
  }
}
複製程式碼

圖片處理

在前端開發中,我們有時會需要不同尺寸的圖片,而一些雲服務都提供有帶連結上新增引數來獲取不同大小圖片的服務。我們可以通過使用一個非基本模組(需安裝)ngx_http_image_filter_module來實現。

    # 圖片縮放處理
    # 這裡約定的圖片處理url格式:以 mysite-base.com/img/路徑訪問
    location ~* /img/(.+)$ {
        alias /Users/cc/Desktop/server/static/image/$1; #圖片服務端儲存地址
        set $width -; #圖片寬度預設值
        set $height -; #圖片高度預設值
        if ($arg_width != "") {
            set $width $arg_width;
        }
        if ($arg_height != "") {
            set $height $arg_height;
        }
        image_filter resize $width $height; #設定圖片寬高
        image_filter_buffer 10M;   #設定Nginx讀取圖片的最大buffer。
        image_filter_interlace on; #是否開啟圖片影像隔行掃描
        error_page 415 = 415.png; #圖片處理錯誤提示圖,例如縮放引數不是數字
    }

複製程式碼

防盜鏈處理

掘金之前也因為被大肆盜鏈使用圖片而開啟了防盜鏈處理,防盜鏈處理是我們需要開啟來保護伺服器的一種方式。

server {
  # 匹配所有圖片
  location ~* \.(gif|jpg|png|bmp)$ {
    # 驗證是否為沒有來路,或者有來路與域名或白名單進行匹配,也可以寫正則,若匹配到欄位為0,否則為1
    valid_referers none blocked server_names www.reaper.com;
    # 如果驗證不通過則返回403錯誤
    if ($invalid_referer) {
      return 403; 
    }
  }
}
複製程式碼

總結

對於Nginx的學習是在配置自己的個人部落格網站Reaper Lee時一邊學習一遍配置完成的,希望能夠幫助一些準備學習或者剛入門Nginx的同學,但對於逐漸全棧化的前端,學會服務端的配置似乎也已經成為了必修的技能。大家也可以關注我的GitHub,一起學習,共同進步!

參考連結: