02.29 要做負載均衡,代碼要滿足什麼條件?

lf10086


當我們的程序只部署一套,不再能滿足訪問量(調用量)的時候,最簡單的橫向擴容的方法就是部署多套應用環境,負載均衡將用戶(客戶端)的訪問平均地分配到每臺服務器上,這樣就可以利用多臺機器的資源,增加系統的負載能力。

那麼要做負載均衡,對我們的系統有什麼要求麼?或者說我們的代碼需要做什麼改造麼?

大部分時候我們的代碼是不需要改造的,但是也要注意這麼幾點。

我們的服務最好是無狀態的,也就是每一次的調用,不依賴於前一次的調用結果,如果前後有依賴,則需要後面的請求攜帶著前一次請求的結果,作為參數進行訪問。

除非負載均衡開啟了會話保持,或者通過一些負載均衡路由策略,讓同一個 IP 的請求始終路由到同一臺服務器上,但是這並不是一個好的解決方案。

通常我們需要保持服務的無狀態性,如果需要做權限認證的話,建議採用 Token 或使用 Redis 做 Session 共享(推薦使用 Token)。

還有一點,可能不一定必須的,不過我覺得也是個不錯的方案,供大家參考。

假如我們有兩臺應用服務器 A 和 B,前面掛一臺負載均衡,當我們需要做應用升級的話,通常可以怎麼做?

  • 通常的辦法是停掉服務器 A,這時候負載均衡會監控到這臺服務器 A 已經無法使用了(比如監控到端口消失),再來的請求會發送給服務器 B;

  • 對服務器 A 升級並啟動,負載均衡監控到 A 恢復了,會將請求發送給 A 和 B;

  • 對服務器 B 做相同的操作。


這樣看似沒有問題,因為在服務器升級的時候,負載均衡不在發送請求到這臺服務器上;但是大家仔細想一想這個過程,如果在停服務器的那一刻,已經有請求進來了並進行處理,但是還沒有返回,這時候停掉服務器,會導致這部分請求發生異常,那麼這個問題如何解決呢?這就需要對程序進行一定的改造了。

  • 應用提供一個接口,返回一個靜態變量的值,只要 true 或 false 兩個狀態;

  • 負載均衡不再監控端口是否消失,而是監控剪口返回的狀態,返回 true 表示應用正常,false 或沒有返回表示不正常;

  • 每次停服務之前,通過接口修改當前應用靜態變量的值為 false;

  • 負載均衡認為該服務器狀態不正常,將不再發送請求到這臺服務器上;

  • 等待幾十秒,這段時間相當於等待當前請求都處理並返回,再停止服務。


“停止服務時,不再接受新的請求,等現有請求都處理完成後再真正停止服務”,這只是一個笨辦法,想要避免以上問題還有更好的辦法,並且對代碼沒有侵入性;有些中間件本身提供了類似的功能,我們只需執行對應的停止服務的命令即可;或者需要在代碼中添加監聽類,當收到 kill 信號的時候,拒絕新的請求,等待一段時間,再結束程序等等。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


大家好,我是IT屠工,很高興回答此問題,希望我的回答可以幫助到你!

什麼是負載均衡

負載均衡主要通過專門的硬件設備或者通過軟件算法實現。通過硬件設備實現的負載均衡效果好、效率高、 性能穩定,但是成本比較高。通過軟件實現的負載均衡主要依賴於均衡算法的選擇和程序的健壯性。均衡 算法也是多種多樣的,常見的有兩大類:即靜態負載均衡算法和動態負載均衡算法。靜態算法實現比較簡 單,在一般網絡環境下也能達到比較好的效果,主要有一般輪詢算法、基於比率的加權輪詢算法以及基於 優先級的加權輪詢算法等。動態負載均衡算法在較為複雜的網絡環境中適應性更強,效果更好,主要有基 於任務量的最少連接優先算法、基於性能的最快響應優先算法、預測算法及動態性能分配算法等。

網絡負載均衡技術的大致原理是利用一定的分配策略將網絡負載平衡地分攤到網絡集群的各個操作單元 上,使得單個重負載任務能夠分擔到多個單元上並行處理,或者使得大量併發訪問或數據 流量分擔到多個 單元上分別處理,從而減少用戶的等待響應時間。


Nginx 服務器負載均衡配置

Nginx 服務器實現了靜態的基於優先級的加權輪詢算法,主要使用的配置是 proxy_pass 指令和 upstream 指令,這些內容實際上很容易理解,關鍵點在於 Nginx 服務器的配置靈活多樣,如何在配置負載均衡的同 時合理地整合其他功能,形成一套可以滿足實際需求的配置方案。

下面的有一些基礎示例片段,當然不可能將所有的配置情況包括在內,希望能夠起到拋磚引玉的效果,同 時也需要大家在實際應用過程中多總結多積累。在配置中需要注意的地方將以註釋的形式添加。


配置實例:

在以下實例片段中,backend 服務器組中所有服務器的優先級全部配置為默認的 weight=1,這樣它 們會按照一般輪詢策略依次接收請求任務。該配置是一個最簡單的實現 Nginx 服務器負載均衡的配置。所 有訪問 www.myweb.name 的請求都會在 backend 服務器組中實現負載均衡。實例代碼如下:

...

upstream backend #配置後端服務器組

{

server 192.168.1.2:80;

server 192.168.1.3:80;

server 192.168.1.4:80; #默認 weight=1

}

server

{

listen 80;

server_name www.myweb.name;


index index.html index.htm;


location / {


proxy_pass http://backend;


prox_set_header Host $host;


}


...


}

由於 Nginx 服務器的 功能在結構上是增量式的,因此 ,我們可以在這些配置的基礎上繼續添加更多功能,比如 Web 緩存等功 能,以及 Gzip 壓縮技術、身份認證、權限管理等。同時在使用 upstream 指令配置服務器組時,可以充 分發揮各個指令的功能,配置出滿足需求、高效穩定、功能豐富的 Nginx 服務器。

歡迎大家關注並點贊,我是@IT屠工,專注IT網絡技術資源分享,普及IT網絡技術

IT屠工


代碼中不能把數據、上傳文件、日誌等保存到本地。

數據庫保存數據

對象存儲保存上傳文件

日誌服務保存系統日誌

Redis或NFS保持session


web架構師自我修煉


1.確保你的接口無狀態,鑑權可以使用token,redis集中化session

2.確保你的接口冪等性,可以為接口生成請求id,過濾請求id,防重,或者可以使用一次性token。

3.確保你的接口集群對等,代碼,數據,都需要對等,通常每臺機器數據源都是一樣的,代碼是相同的。同時機器的配置也是相同的。


分享到:


相關文章: