咱們真實的服務器不該該直接暴露到公網上去,不然更加容易泄露服務器的信息,也更加容易受到攻擊。一個比較「平民化」的方案是使用Nginx反向代理它。今天就來聊一聊使用Nginx反向代理的一些能力,Nginx代理能幫助咱們實現不少很是有效的API控制功能。這也解釋了我爲何一直推薦使用Nginx來代理咱們的Spring Boot應用。nginx
Nginx已經不用太多的讚美了,它已經獲得了業界的普遍承認。咱們就聊聊它具體可以實現什麼功能。web
這是針對服務器端咱們最經常使用的功能,一臺具備公網的Nginx服務器能夠代理和它能進行內網通訊的真實的服務器。讓咱們的服務器不直接對外暴露,增長其抗風險能力。正則表達式
假如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中匹配的路徑部分代理走;若是不以/
結尾,也會代理匹配的路徑部分。
Nginx還提供了一個rewrite
功能讓咱們在請求到達服務器時重寫URI,有點相似Servlet Filter的意味,對請求進行一些預處理。api
在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
)或本身設置的變量做爲條件,結合正則表達式和標誌位(last
、break
、redirect
、permanent
)實現URI重寫以及重定向。session
以前不少同窗在羣裏問如何在Spring Boot項目中配置HTTPS,我都推薦使用Nginx來作這個事情。 Nginx比Spring Boot中配置SSL要方便的多,並且不影響咱們本地開發。Nginx中HTTPS的相關配置根據下面的改一改就能用:app
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來提升用戶體驗。
通常項目都是從小作到大起來的,起步的時候部署一個服務器就夠用了,若是你的項目用戶多了起來,首先恭喜你,說明你的項目方向很對。可是伴隨而來還有服務器壓力,你必定不想服務器宕機帶來的各類損失,你須要快速提升服務器的抗壓能力,或者你想不停機維護避免業務中斷,這些均可以經過Nginx的負載均衡來實現,並且很是簡單。假如felord.cn
咱們部署了三個節點:負載均衡
輪番派發請求,這種配置是最簡單的:
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,這樣每一個客戶端將固定訪問服務器,若是服務器宕機,須要手動剔除。
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實現動態負載均衡。咱們是否是藉助於此能夠開發一個灰度發佈功能呢?
經過對Nginx的配置,咱們能夠實現漏桶算法和令牌桶算法,經過限制單位時間的請求數、同一時間的鏈接數來限制訪問速度。這一塊我並無深刻研究過這裏就提一提,你能夠查詢相關的資料研究。
Nginx很是強大,推薦使用它來代理咱們的後端應用,咱們能夠經過配置實現不少有用的功能,而沒必要進行一些非業務邏輯的編碼來實現,若是你在Spring Boot中實現限流、配置SSL的話,麻煩不說,還影響本地開發,使用Nginx可讓咱們專心到業務中去。能夠說Nginx在這裏充當了一個小網關的做用,其實不少知名網關底層都是Nginx,好比Kong、Orange、Apache APISIX等,若是你有興趣能夠玩一玩Nginx的高級形態Openresty。另外我這裏也有一份很是不錯的Nginx入門資料送給你,能夠關注:碼農小胖哥 回覆 nginx 獲取。
關注公衆號:Felordcn 獲取更多資訊