徹底搞懂 Nginx 的五大應用場景

一、HTTP 服務器

Nginx 本身也是一個靜態資源的服務器,當只有靜態資源的時候,就可以使用 Nginx 來做服務器,如果一個網站只是靜態頁面的話,那麼就可以通過這種方式來實現部署。

1、 首先在文檔根目錄Docroot(/usr/local/var/www)下創建 html 目錄, 然後在 html 中放一個 test.html;

2、 配置nginx.conf中的 server

user mengday staff;

http {
    server {
        listen       80;
        server_name  localhost;
        client_max_body_size 1024M;

        # 默認location
        location / {
            root   /usr/local/var/www/html;
            index  index.html index.htm;
        }
    }
}

3、訪問測試

注意:如果訪問圖片出現 403 Forbidden 錯誤,可能是因爲 nginx.conf 的第一行 user 配置不對,默認是 #user nobody; 是註釋的,linux 下改成 user root; macos 下改成 user 用戶名 所在組; 然後重新加載配置文件或者重啓,再試一下就可以了, 用戶名可以通過 who am i 命令來查看。

4、指令簡介

5、location uri 正則表達式

小括號 () 之間匹配的內容,可以在後面通過$1來引用,$2表示的是前面第二個 () 裏的內容。正則裏面容易讓人困惑的是\轉義特殊字符。

二、靜態服務器

在公司中經常會遇到靜態服務器,通常會提供一個上傳的功能,其他應用如果需要靜態資源就從該靜態服務器中獲取。

1、在/usr/local/var/www 下分別創建 images 和 img 目錄,分別在每個目錄下放一張test.jpg

http {
    server {
        listen       80;
        server_name  localhost;


        set $doc_root /usr/local/var/www;

        # 默認location
        location / {
            root   /usr/local/var/www/html;
            index  index.html index.htm;
        }

        location ^~ /images/ {
            root $doc_root;
       }

       location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js){
           root $doc_root/img;
       }
    }
}

自定義變量使用 set 指令,語法 set 變量名值; 引用使用變量名值; 引用使用變量名; 這裏自定義了 doc_root 變量。

靜態服務器 location 的映射一般有兩種方式:

訪問http://localhost/test.jpg 會映射到 $doc_root/img

訪問http://localhost/images/test.jpg 當同一個路徑滿足多個 location 時,優先匹配優先級高的 location,由於^~ 的優先級大於 ~, 所以會走/images/對應的 location

常見的 location 路徑映射路徑有以下幾種:

location 優先級

當一個路徑匹配多個 location 時究竟哪個 location 能匹配到時有優先級順序的,而優先級的順序於 location 值的表達式類型有關,和在配置文件中的先後順序無關。相同類型的表達式,字符串長的會優先匹配。推薦:Java 面試題大全

以下是按優先級排列說明:

優先級搜索問題:不同類型的 location 映射決定是否繼續向下搜索

location 優先級從高到底:

(location =) > (location 完整路徑) > (location ^~ 路徑) > (location ~,~* 正則順序) > (location 部分起始路徑) > (/)

location = / {
    # 精確匹配/,主機名後面不能帶任何字符串 /
    [ configuration A ]
}
location / {
    # 匹配所有以 / 開頭的請求。
    # 但是如果有更長的同類型的表達式,則選擇更長的表達式。
    # 如果有正則表達式可以匹配,則優先匹配正則表達式。
    [ configuration B ]
}
location /documents/ {
    # 匹配所有以 /documents/ 開頭的請求,匹配符合以後,還要繼續往下搜索。
    # 但是如果有更長的同類型的表達式,則選擇更長的表達式。
    # 如果有正則表達式可以匹配,則優先匹配正則表達式。
    [ configuration C ]
}
location ^~ /images/ {
    # 匹配所有以 /images/ 開頭的表達式,如果匹配成功,則停止匹配查找,停止搜索。
    # 所以,即便有符合的正則表達式location,也不會被使用
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg){
    # 匹配所有以 gif jpg jpeg結尾的請求。
    # 但是 以 /images/開頭的請求,將使用 Configuration D,D具有更高的優先級
    [ configuration E ]
}

location /images/ {
    # 字符匹配到 /images/,還會繼續往下搜索
    [ configuration F ]
}


location = /test.htm {
    root   /usr/local/var/www/htm;
    index  index.htm;
}

注意:location 的優先級與 location 配置的位置無關

三、反向代理

反向代理應該是 Nginx 使用最多的功能了,反向代理 (Reverse Proxy) 方式是指以代理服務器來接受 internet 上的連接請求,然後將請求轉發給內部網絡上的服務器,並將從服務器上得到的結果返回給 internet 上請求連接的客戶端,此時代理服務器對外就表現爲一個反向代理服務器。

簡單來說就是真實的服務器不能直接被外部網絡訪問,所以需要一臺代理服務器,而代理服務器能被外部網絡訪問的同時又跟真實服務器在同一個網絡環境,當然也可能是同一臺服務器,端口不同而已。

反向代理通過proxy_pass指令來實現。

啓動一個 Java Web 項目,端口號爲 8081

server {
    listen       80;
    server_name  localhost;

    location / {
        proxy_pass http://localhost:8081;
        proxy_set_header Host $host:$server_port;
        # 設置用戶ip地址
         proxy_set_header X-Forwarded-For $remote_addr;
         # 當請求服務器出錯去尋找其他服務器
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; 
    }

}

當我們訪問 localhost 的時候,就相當於訪問 localhost:8081

四、負載均衡

負載均衡也是 Nginx 常用的一個功能,負載均衡其意思就是分攤到多個操作單元上進行執行,例如 Web 服務器、FTP 服務器、企業關鍵應用服務器和其它關鍵任務服務器等,從而共同完成工作任務。

簡單而言就是當有 2 臺或以上服務器時,根據規則隨機的將請求分發到指定的服務器上處理,負載均衡配置一般都需要同時配置反向代理,通過反向代理跳轉到負載均衡。而 Nginx 目前支持自帶 3 種負載均衡策略,還有 2 種常用的第三方策略。

負載均衡通過 upstream 指令來實現。推薦:Java 面試題大全

1. RR(round robin : 輪詢 默認)

每個請求按時間順序逐一分配到不同的後端服務器,也就是說第一次請求分配到第一臺服務器上,第二次請求分配到第二臺服務器上,如果只有兩臺服務器,第三次請求繼續分配到第一臺上,這樣循環輪詢下去,也就是服務器接收請求的比例是 1:1, 如果後端服務器 down 掉,能自動剔除。輪詢是默認配置,不需要太多的配置

同一個項目分別使用 8081 和 8082 端口啓動項目

upstream web_servers {  
   server localhost:8081;  
   server localhost:8082;  
}

server {
    listen       80;
    server_name  localhost;
    #access_log  logs/host.access.log  main;


    location / {
        proxy_pass http://web_servers;
        # 必須指定Header Host
        proxy_set_header Host $host:$server_port;
    }
 }

訪問地址仍然可以獲得響應 http://localhost/api/user/login?username=zhangsan&password=111111 ,這種方式是輪詢的

2. 權重

指定輪詢幾率,weight 和訪問比率成正比, 也就是服務器接收請求的比例就是各自配置的 weight 的比例,用於後端服務器性能不均的情況, 比如服務器性能差點就少接收點請求,服務器性能好點就多處理點請求。

upstream test {
    server localhost:8081 weight=1;
    server localhost:8082 weight=3;
    server localhost:8083 weight=4 backup;
}

示例是 4 次請求只有一次被分配到 8081 上,其他 3 次分配到 8082 上。backup 是指熱備,只有當 8081 和 8082 都宕機的情況下才走 8083

3. ip_hash

上面的 2 種方式都有一個問題,那就是下一個請求來的時候請求可能分發到另外一個服務器,當我們的程序不是無狀態的時候 (採用了 session 保存數據),這時候就有一個很大的很問題了,比如把登錄信息保存到了 session 中,那麼跳轉到另外一臺服務器的時候就需要重新登錄了,所以很多時候我們需要一個客戶只訪問一個服務器,那麼就需要用 iphash 了,iphash 的每個請求按訪問 ip 的 hash 結果分配,這樣每個訪客固定訪問一個後端服務器,可以解決 session 的問題。

upstream test {
    ip_hash;
    server localhost:8080;
    server localhost:8081;
}

4. fair(第三方)

按後端服務器的響應時間來分配請求,響應時間短的優先分配。這個配置是爲了更快的給用戶響應

upstream backend {
    fair;
    server localhost:8080;
    server localhost:8081;
}

5. url_hash(第三方)

按訪問 url 的 hash 結果來分配請求,使每個 url 定向到同一個後端服務器,後端服務器爲緩存時比較有效。在 upstream 中加入 hash 語句,server 語句中不能寫入 weight 等其他的參數,hash_method是使用的 hash 算法

upstream backend {
    hash $request_uri;
    hash_method crc32;
    server localhost:8080;
    server localhost:8081;
}

以上 5 種負載均衡各自適用不同情況下使用,所以可以根據實際情況選擇使用哪種策略模式, 不過 fair 和 url_hash 需要安裝第三方模塊才能使用。

五、動靜分離

動靜分離是讓動態網站裏的動態網頁根據一定規則把不變的資源和經常變的資源區分開來,動靜資源做好了拆分以後,我們就可以根據靜態資源的特點將其做緩存操作,這就是網站靜態化處理的核心思路。

upstream web_servers {  
       server localhost:8081;  
       server localhost:8082;  
}

server {
    listen       80;
    server_name  localhost;

    set $doc_root /usr/local/var/www;

    location ~* \.(gif|jpg|jpeg|png|bmp|ico|swf|css|js){
       root $doc_root/img;
    }

    location / {
        proxy_pass http://web_servers;
        # 必須指定Header Host
        proxy_set_header Host $host:$server_port;
    }

    error_page 500 502 503 504  /50x.html;  
    location = /50x.html {  
        root $doc_root;
    }

 }

六、其他

1.return 指令

返回 http 狀態碼 和 可選的第二個參數可以是重定向的 URL

location /permanently/moved/url {
    return 301 http://www.example.com/moved/here;
}

2. rewrite 指令

重寫 URI 請求 rewrite,通過使用 rewrite 指令在請求處理期間多次修改請求 URI,該指令具有一個可選參數和兩個必需參數。

第一個 (必需) 參數是請求 URI 必須匹配的正則表達式。

第二個參數是用於替換匹配 URI 的 URI。

可選的第三個參數是可以停止進一步重寫指令的處理或發送重定向 (代碼 301 或 302) 的標誌

location /users/ {
    rewrite ^/users/(.*)$ /show?user=$1 break;
}

3. error_page 指令

使用 error_page 指令,您可以配置 NGINX 返回自定義頁面以及錯誤代碼,替換響應中的其他錯誤代碼,或將瀏覽器重定向到其他 URI。在以下示例中,error_page指令指定要返回 404 頁面錯誤代碼的頁面 (/404.html)。

error_page 404 /404.html;

4. 日誌

訪問日誌:需要開啓壓縮 gzip on; 否則不生成日誌文件,打開log_formataccess_log註釋

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  /usr/local/etc/nginx/logs/host.access.log  main;

gzip  on;

5. deny 指令

# 禁止訪問某個目錄
location ~* \.(txt|doc)${
    root $doc_root;
    deny all;
}

6. 內置變量

nginx 的配置文件中可以使用的內置變量以美元符$開始,也有人叫全局變量。其中,部分預定義的變量的值是可以改變的。另外,關注 Java 知音公衆號,回覆 “後端面試”,送你一份面試題寶典!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/HSClbgx_m_IVhfOUCF0RBg