大家好,我是哪吒。
本系列為SpringCloud微服務系列,先從微服務的入口Nginx開始學習,讀哪吒程式設計,品技術人生。
一、系統架構演變
最開始接觸Java語言的時候,我寫的第一個專案是圖書管理系統,當時是用JSP+servlet寫的,感覺很吊的樣子,全班領先水平。
慢慢的變成了JSP+SSM架構。
到現在單體架構最流行的SpringBoot+Vue。
但是,隨著業務量的不斷增大,你會發現,這些單體架構,已經無法滿足資料日益膨脹的今天,動不動就幾萬、幾十萬的QPS,我記得當初200QPS,我就覺得挺嚇人了。
為了解決效能問題,慢慢的微服務SpringCloud架構浮出水面,微服務的核心理念是將應用細粒化,將單一應用拆分成若干個小應用,每個小應用提供單一的業務功能,獨立部署,服務之間相互呼叫,降低程式耦合度,解決單臺伺服器當機的問題。
微服務提供了:
- 高可用:當某個節點伺服器當機後,可以迅速將流量轉移到其它節點;
- 高效能:多臺伺服器對外提供相同的服務,提升程式的吞吐量;
- 高擴充套件:當業務發生激增時,可以透過增加節點的方式,解決效能問題;
注:本章的重點是Nginx,微服務其它元件就不畫了。
二、什麼是Nginx?
Nginx是俄羅斯人Igor Sysoev編寫的一款高效能 HTTP 和反向代理伺服器。Nginx選擇了epoll和kqueue作為網路I/O 模型,在高連線併發的情況下,Nginx是Apache伺服器不錯的替代品,它能夠支援高達50000個併發連線數的響應,執行穩定,且記憶體、CPU等系統資源消耗非常低。
三、servername匹配規則
- 完整匹配
- 萬用字元匹配
- 正則匹配
正則匹配格式,必須以~開頭,比如server_name ~^www\d+\.nzbc\.com$;
。如果沒有~開頭,則Nginx會判定為完整匹配,在邏輯上,需要新增^和$錨定符號。正則匹配格式中.為正則元字元,需要透過反斜線進行轉義,如果正在表示式中包含{},需要用雙引號引用起來,避免報錯。
四、正向代理與反向代理
1、正向代理
正向代理伺服器一般位於使用者和伺服器之間,使用者透過正向代理伺服器訪問應用伺服器獲取資源。
最常見的例子就是,我們訪問一個外國網站,該網站無法在國內直接訪問,但是可以透過代理伺服器訪問,也就是說,使用者向正向代理伺服器傳送一個請求並指定目標,然後正向代理伺服器向目標伺服器(外國網站)轉交請求並將獲得的內容返回給使用者。
正向代理伺服器,代理的是客戶端,去和服務端互動。
2、反向代理
反向代理伺服器一般位於使用者和伺服器之間,使用者訪問反向代理伺服器獲取應用伺服器資源,使用者不知道應用伺服器的地址,是由代理伺服器轉發的,有降低網路和伺服器的負載,提高訪問效率的作用。
反向代理伺服器,代理的是服務端,去和客戶端互動。
Nginx就是一款高效能的反向代理伺服器。
3、LVS
先說結論,LVS解決了Nginx單機效能瓶頸的問題。
LVS主要用於多伺服器負載均衡,工作在網路的第四層,可以實現高效能、高可用的伺服器叢集技術,採用同步請求轉發的策略。
LVS支援的併發量要比Nginx高,可以配合keepalived使用,將Nginx作為LVS的節點機器,因為Nginx在網路的第七層,功能上肯定強於LVS。
使用者透過Nginx訪問應用伺服器,應用伺服器直接將資料返回給機房路由,返回時不走Nginx了,降低了Nginx的效能消耗。
五、負載均衡策略
1、輪詢
預設使用輪詢方式,逐一轉發訪問,這種情況適合無狀態請求,會話無法保持,可以透過基於客戶端實現會話保持。
會話保持方式:
(1)基於session實現:
session用於儲存客戶端使用者資訊,一般不在伺服器儲存session,可以透過SpringSession將session儲存到一個Redis伺服器中,再次訪問時,可以到Redis伺服器中獲取session,實現session共享。
(2)基於cookie實現,無狀態的會話保持方式:
客戶端訪問時,先到許可權校驗伺服器校驗許可權,生成一個cookie,並進行加密,只有伺服器能解密,客戶端沒密碼無法解密,客戶端攜帶此cookie再次訪問應用伺服器,應用伺服器進行解密校驗,完成無狀態的會話保持。
2、權重
透過upstream
進行權重的定義。
- weight:權重
- down:下線不用了
- backup:備用伺服器
修改配置檔案後,需要透過systemctl reload nginx
命令重啟Nginx。
nginx.conf配置如下
http{
upstream httpnz {
server 192.168.66.1 weight=1 down;
server 192.168.66.2 weight=5 backup;
server 192.168.66.3 weight=10;
}
server{
listen 80;
server_name nzbc;
location / {
proxy_pass http://httpnz;
}
error_page 500.html;
location = /500.html{
root html;
}
}
}
3、ip_hash
每個請求按訪問ip的hash結果分配,對映到固定某一臺的伺服器,會導致負載均衡不平衡。
當此應用伺服器當機後,session會丟失,再次發起請求時,會重新固定訪問另一臺正常的應用伺服器,並實現會話保持。
4、least_conn
最少連線訪問。
5、url_hash
根據訪問的url轉發請求,定向流量轉發。
每個請求按訪問url的hash結果分配,對映到固定的某一臺伺服器,會話無法保持。
一般在獲取本地資源時使用(且本地資源不在同一臺伺服器上),比如透過地址1獲取圖片資源、透過地址2獲取pdf協議資源。
6、fair
根據伺服器響應時間轉發請求。
7、小結
最常用的負載均衡策略是配置權重,其它的形式,不是很常用。
ip_hash、least_conn、url_hash、fair
,這幾種形式無法實現動態Nginx上下線(新增或減少Nginx伺服器),而且還會造成流量傾斜的問題,如果瞬時流量比較爆炸的時候,會將某個伺服器直接幹蹦。
六、動靜分離
動靜分離的最終目的是將獲取靜態資源和動態資源分離開,提升伺服器效能和高可用性。
配置靜態資源,nginx.conf配置如下
http{
upstream httpnz {
server 192.168.66.1 weight=1 down;
server 192.168.66.2 weight=5 backup;
server 192.168.66.3 weight=10;
}
server{
listen 80;
server_name nzbc;
location / {
proxy_pass http://httpnz;
}
location ~*/(js/img/css) {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
}
七、URLRewrite
URLRewrite是實現URL重寫的關鍵指令,根據regex (正規表示式)部分內容,進行重定向。
flag標記說明:
- break,本條匹配完成後即終止;
- last,本條匹配完成後,繼續向下匹配;
- redirect,返回302臨時重定向;
- permanent,返回301永久重定向;
配置URLRewrite,nginx.conf配置如下
http{
upstream httpnz {
server 192.168.66.1 weight=1 down;
server 192.168.66.2 weight=5 backup;
server 192.168.66.3 weight=10;
}
server{
listen 80;
server_name nzbc;
location / {
rewrite ^/([0-9]+).html$ /index.jsp?pageNum=$1 break;
proxy_pass http://httpnz;
}
location ~*/(js/img/css) {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html{
root html;
}
}
}