為什么我推薦Nginx作為后端服務器代理


1. 前言

我們真實的服務器不應該直接暴露到公網上去,否則更加容易泄露服務器的信息,也更加容易受到攻擊。一個比較“平民化”的方案是使用Nginx反向代理它。今天就來聊一聊使用Nginx反向代理的一些能力,Nginx代理能幫助我們實現很多非常有效的API控制功能。這也解釋了我為什么一直推薦使用Nginx來代理我們的Spring Boot應用。

2. Nginx可以提供哪些能力

Nginx已經不用太多的贊美了,它已經得到了業界的廣泛認可。我們就聊聊它具體能夠實現什么功能。

2.1 代理能力

這是針對服務器端我們最常用的功能,一台具有公網的Nginx服務器可以代理和它能進行內網通信的真實的服務器。讓我們的服務器不直接對外暴露,增加其抗風險能力。

Nginx反向代理web應用

假如Nginx服務器192.168.1.8可以和同一內網網段的192.168.1.9的應用服務器進行通信,同時Nginx服務器具有公網能力並將公網綁定到域名felord.cn上。那么我們Nginx代理的對應的配置(nginx.conf)是這樣的:

    server {
        listen       80;
        server_name  felord.cn;
    #   ^~ 表示uri以某個常規字符串開頭,如果匹配到,則不繼續往下匹配。不是正則匹配
        location ^~  /api/v1 {
            proxy_set_header Host $host;
            proxy_pass http://192.168.1.9:8080/;
        }
    }

經過以上配置后我們服務器真實的接口地址是http://192.168.1.9:8080/foo/get就可以通過http://felord.cn/api/v1/foo/get訪問。

proxy_pass如果以/結尾,就相當於是絕對根路徑,那么Nginx不會把location中匹配的路徑部分代理走;如果不以/結尾,也會代理匹配的路徑部分。

2.2 Rewrite功能

Nginx還提供了一個rewrite功能讓我們在請求到達服務器時重寫URI,有點類似Servlet Filter的意味,對請求進行一些預處理。

Nginx包含rewrite的流程

2.1的例子中如果我們要實現如果判斷請求為POST的話返回405,只需要更改配置為:

location ^~  /api/v1 {
    proxy_set_header Host $host;
    if ($request_method = POST){
      return 405;
    }
    proxy_pass http://192.168.1.9:8080/;
}

你可以使用Nginx提供的全局變量(如上面配置中的$request_method)或自己設置的變量作為條件,結合正則表達式和標志位(lastbreakredirectpermanent)實現URI重寫以及重定向。

2.3 配置HTTPS

之前很多同學在群里問如何在Spring Boot項目中配置HTTPS,我都推薦使用Nginx來做這個事情。 NginxSpring Boot中配置SSL要方便的多,而且不影響我們本地開發。NginxHTTPS的相關配置根據下面的改一改就能用:

http{
    #http節點中可以添加多個server節點
    server{
        #ssl 需要監聽443端口
        listen 443;
        # CA證書對應的域名
        server_name felord.cn;
        # 開啟ssl
        ssl on;
        # 服務器證書絕對路徑
        ssl_certificate /etc/ssl/cert_felord.cn.crt;
        # 服務器端證書key絕對路徑 
        ssl_certificate_key /etc/ssl/cert_felord.cn.key;
        ssl_session_timeout 5m;
        # 協議類型
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        # ssl算法列表 
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
        #  是否 服務器決定使用哪種算法  on/off   TLSv1.1 的話需要開啟
        ssl_prefer_server_ciphers on;
        
        location ^~  /api/v1 {
            proxy_set_header Host $host;
            proxy_pass http://192.168.1.9:8080/;
        }
    }
    # 如果用戶通過 http 訪問 直接重寫 跳轉到 https 這個是一個很有必要的操作
    server{
        listen 80;
        server_name felord.cn;
        rewrite ^/(.*)$ https://felord.cn:443/$1 permanent;
    }

}

這里就用到了rewrite來提高用戶體驗。

2.4 負載均衡

一般項目都是從小做到大起來的,起步的時候部署一個服務器就夠用了,如果你的項目用戶多了起來,首先恭喜你,說明你的項目方向很對。但是伴隨而來還有服務器壓力,你一定不想服務器宕機帶來的各種損失,你需要快速提高服務器的抗壓能力,或者你想不停機維護避免業務中斷,這些都可以通過Nginx的負載均衡來實現,而且非常簡單。假如felord.cn我們部署了三個節點:

Nginx 負載均衡

最簡單的輪詢策略

輪番派發請求,這種配置是最簡單的:

http {
    
    upstream app {
           # 節點1
           server 192.168.1.9:8080;
           # 節點2
           server 192.168.1.10:8081;
           # 節點3
           server 192.168.1.11:8082;
    }
    
    server {
        listen       80;
        server_name  felord.cn;
    #   ^~ 表示uri以某個常規字符串開頭,如果匹配到,則不繼續往下匹配。不是正則匹配
        location ^~  /api/v1 {
            proxy_set_header Host $host;
            # 負載均衡
            proxy_pass http://app/;
        }
    }
}

加權輪詢策略

指定輪詢幾率,weight和訪問比率成正比,用於后端服務器性能不均的情況:

upstream app {
       # 節點1
       server 192.168.1.9:8080 weight = 6;
       # 節點2
       server 192.168.1.10:8081 weight = 3;
       # 節點3
       server 192.168.1.11:8082 weight = 1;
}

最終請求處理數將為6:3:1 進行分配。其實簡單輪詢可以看作所有的權重均分為1。輪詢宕機可自動剔除。

IP HASH

根據訪問IP進行Hash,這樣每個客戶端將固定訪問服務器,如果服務器宕機,需要手動剔除。

upstream app {
       ip_hash;
       # 節點1
       server 192.168.1.9:8080 weight = 6;
       # 節點2
       server 192.168.1.10:8081 weight = 3;
       # 節點3
       server 192.168.1.11:8082 weight = 1;
}

最少連接

請求將轉發到連接數較少的服務器上,充分利用服務器資源:

upstream app {
       least_conn;
       # 節點1
       server 192.168.1.9:8080 weight = 6;
       # 節點2
       server 192.168.1.10:8081 weight = 3;
       # 節點3
       server 192.168.1.11:8082 weight = 1;
}

其它方式

我們可以借助一些插件來實現其它模式的負載均衡,例如借助於nginx-upsync-module實現動態負載均衡。我們是不是借助於此可以開發一個灰度發布功能呢?

2.5 限流

通過對Nginx的配置,我們可以實現漏桶算法和令牌桶算法,通過限制單位時間的請求數、同一時間的連接數來限制訪問速度。這一塊我並沒有深入研究過這里就提一提,你可以查詢相關的資料研究。

3. 總結

Nginx非常強大,推薦使用它來代理我們的后端應用,我們可以通過配置實現很多有用的功能,而不必進行一些非業務邏輯的編碼來實現,如果你在Spring Boot中實現限流、配置SSL的話,麻煩不說,還影響本地開發,使用Nginx可以讓我們專心到業務中去。可以說Nginx在這里充當了一個小網關的作用,其實很多知名網關底層都是Nginx,比如KongOrangeApache APISIX等,如果你有興趣可以玩一玩Nginx的高級形態Openresty。另外我這里也有一份非常不錯的Nginx入門資料送給你,可以關注:碼農小胖哥 回復 nginx 獲取。

關注公眾號:Felordcn 獲取更多資訊

個人博客:https://felord.cn


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM