一、前置知識
1.1 負載均衡定義
負載均衡指的是將網絡請求通過不同的算法分配到不同的服務器上的技術,從而提升系統的性能。
1.2 負載均衡工具
負載均衡工具可以分分為客戶端負載均衡工具和服務端負載均衡工具,它們的區別如下。
表1-1 負載均衡工具分類[1]
?維度? | ?客戶端負載均衡工具? | ?服務端負載均衡工具? |
---|---|---|
?決策位置? | 客戶端代碼中實現 | 中間層(如Nginx、負載均衡器) |
?靈活性? | 高(支持自定義算法,如業務哈希) | 較低(依賴中間層配置) |
?性能開銷? | 客戶端需計算實例選擇,可能增加延遲 | 額外網絡跳轉,可能成為瓶頸 |
?容錯性? | 客戶端需處理重試/降級 | 中間層自動剔除故障節點 |
?服務發現? | 強依賴注冊中心(如Eureka) | 可靜態配置或動態集成 |
?適用協議? | HTTP、gRPC、RPC | HTTP、TCP、UDP |
1.3 負載均衡算法
表1-2 負載均衡算法[2]
?算法? | ?工作原理? | ?適用場景? | ?優點? | ?缺點? |
---|---|---|---|---|
?輪詢(Round Robin)?? | 按順序依次分配請求(如A->B->C->A->B) | 服務器性能相近、無狀態服務(如靜態資源) | 簡單公平,易于實現 | 忽略服務器負載差異,性能不均時效率低 |
?加權輪詢(Weighted RR)?? | 根據服務器性能分配權重(如5:3:2),高權重服務器獲得更多請求 | 服務器性能差異明顯(如新舊硬件混合) | 按能力分配資源,優化利用率 | 需手動配置權重,無法動態響應負載變化 |
?最少連接(Least Connections)?? | 優先選擇當前連接數最少的服務器 | 長連接服務(數據庫、視頻流) | 動態適應負載,避免服務器過載 | 忽略服務器處理能力差異 |
?加權最少連接(Weighted LC)?? | 結合服務器權重和當前連接數,選擇(連接數/權重)最小的服務器 | 高性能異構集群(如混合云環境) | 兼顧性能與實時負載,資源利用率高 | 算法復雜,需實時監控服務器狀態 |
?源IP哈希(IP Hash)?? | 根據客戶端IP計算哈希值,固定分配到同一服務器 | 需會話保持的應用(如購物車、登錄狀態) | 保證會話一致性 | 服務器故障時關聯用戶受影響 |
?隨機(Random)?? | 完全隨機分配請求 | 測試環境或簡單負載場景 | 實現簡單,無狀態依賴 | 分配不可控,可能造成負載不均 |
?最快響應時間(Fastest Response)?? | 選擇響應時間最短的服務器 | 對延遲敏感的應用(如金融交易) | 提升用戶體驗 | 需持續監控服務器響應時間 |
?一致性哈希(Consistent Hashing)?? | 哈希環映射請求,服務器擴容/縮容時僅影響少量請求 | 分布式緩存(Redis集群) | 減少節點變動的影響 | 實現復雜度較高 |
?動態性能分配(Dynamic Ratio)?? | 根據CPU、內存等實時指標動態調整流量分配 | 服務器性能波動大的場景 | 精準匹配當前負載 | 需高性能監控系統支持 |
二、Ribbon實戰
2.1 項目結構
本項目使用Eureka作為注冊中心,使用方法參見:Ereka實戰。
圖2-1 項目結構?
服務列表如下。其中SpringCloudEurekaProductApplication02和SpringCloudEurekaProductApplication為product服務的實例,創建步驟見:IDEA中一個服務創建多個實例。
圖2-2 服務實例?
2.2 order模塊新建以下代碼
創建RestTemplate對象,并添加@LoadBalanced注解開啟負載均衡。
@Configuration
public class LoadBalanceConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}
創建控制器訪問product服務。
@RestController
@RequestMapping("/loadBalance")
public class LoadBalanceController {@Autowiredprivate RestTemplate restTemplate;@RequestMapping("/test")public String test(){String url = String.format("http://%s/loadTest", "spring-cloud-eureka-product");ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class);return forEntity.getBody();}
}
2.2 product模塊新建代碼
@RequestMapping
@RestController
public class LoadBalanceController {// order在配置文件中設置@Value("${order}")private Integer order;@RequestMapping("/loadTest")public String loadTest(){return "服務器:" + order;}
}
2.3 運行
分別啟動server、product、product02、order服務,啟動成功后,訪問注冊中http://localhost:8080/,結果如下圖所示。
圖2-3 注冊中心?
訪問兩次http://localhost:9003/loadTest,分別得到以下結果。后面的數字是兩個product服務激活的配置文件中配置的order的值,分別為1和2。
圖2-4 訪問結果?
三、總結
核心點就是創建RestTemplate,然后添加@LoadBalance注解,使用RestTemplate對象方法時自動實現負載均衡。
參考
[1][2] 騰訊元寶