微服務流量分發核心:Spring Cloud 負載均衡解析

目錄

理解負載均衡

負載均衡的實現方式

服務端負載均衡

客戶端負載均衡

Spring Cloud LoadBalancer快速上手

常見的負載均衡策略

自定義負載均衡策略

LoadBalancer 原理

理解負載均衡

在 Spring Cloud 微服務架構中,負載均衡(Load Balance)是實現服務高可用、提高系統吞吐量的核心機制之一。它通過將請求合理分發到多個服務實例,避免單個實例過載,同時實現故障自動隔離,是服務調用鏈路中的關鍵環節。

在微服務中,一個服務通常會部署多個實例(如產品信息服務可能有product-service:9090product-service:9091product-service:9092等)。負載均衡的核心目標是:

  1. 請求分發:將服務消費者的請求均勻分配到多個服務提供者實例,避免單點壓力過大。

  2. 故障隔離:自動排除不可用的實例(如宕機、健康檢查失敗),確保請求只發送到可用實例。

  3. 彈性伸縮支持:當服務實例擴縮容時,能自動感知并調整分發策略,無需人工干預。

負載均衡的實現方式

負載均衡分為服務端負載均衡客戶端負載均衡

服務端負載均衡

比較有名的服務端負載均衡器是Nginx,請求先到達Nginx負載均衡器,然后通過負載均衡算法,在多個服務器之間選擇?個進行訪問。

客戶端負載均衡

把負載均衡的功能以庫的方式集成到客戶端,而不再是由?臺指定的負載均衡設備集中提供。

比如Spring Cloud的Ribbon,請求發送到客戶端,客戶端從注冊中心(比如Eureka)獲取服務列表,在發送請求前通過負載均衡算法選擇?個服務器,然后進行訪問。

Ribbon是Spring Cloud早期的默認實現,由于不維護了,所以最新版本的Spring Cloud負載均衡集成的是Spring Cloud LoadBalancer(Spring Cloud官方維護)

Spring Cloud LoadBalancer快速上手

Spring Cloud LoadBalancer 并不是一個獨立服務,而是一個 客戶端負載均衡庫

調用流程大致是:

  1. 獲取服務名(例如調用 http://inventory-service/api/stock/1,這里的 inventory-service 就是服務名)。

  2. 去服務注冊中心查找(Nacos、Eureka、Consul…)獲取該服務的所有實例地址(IP:Port)。

  3. 負載均衡策略選擇:比如輪詢、隨機、權重優先、本地優先。

  4. 發起請求到選定的實例

使用方式

RestTemplate 加上 @LoadBalanced 注解:

@Configuration
public class RestTemplateConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate() {return new RestTemplate();}
}

使用時直接寫服務名:

@Autowired
private RestTemplate restTemplate;
?
public OrderDO selectOrderById(Integer id) {OrderDO orderDO = orderMapper.selectOrderById(id);//這里的 product-service 不再是域名,而是注冊中心里的 服務名。String url = "http://product-service/product/"+orderDO.getProductId();//遠程調用獲取數據ProductDO productDO = restTemplate.getForObject(url, ProductDO.class);orderDO.setProductDO(productDO);return orderDO;
}

啟動服務進行測試

前置環境配置可參考Spring Cloud——服務注冊與服務發現原理與實現-CSDN博客

測試負載均衡

連續多次發起請求: http://127.0.0.1:8080/order/1

觀察product-service的日志, 會發現請求被分配到這3個實例上了

常見的負載均衡策略

Spring Cloud LoadBalancer 默認策略是 RoundRobin(輪詢)。 常見策略包括:

  • RoundRobin(輪詢):依次選擇服務實例,分配均勻。

  • Random(隨機):隨機選一個實例,適合流量比較小的場景。

  • Weighted(權重):根據權重選擇(Nacos 支持,可以按版本或機房區分)。

  • ZonePreference(區域優先):優先選擇同機房的實例,跨機房兜底。

可以通過自定義配置擴展策略。

自定義負載均衡策略

@Configuration
public class LoadBalancerConfig {@BeanReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,LoadBalancerClientFactory loadBalancerClientFactory) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name,ServiceInstanceListSupplier.class), name);}
}

注意: 該類需要滿足:

  1. 不用 @Configuration 注釋

  2. 在組件掃描范圍內

@LoadBalancerClient(name = "product-service", configuration = LoadBalancerConfig.class)
@Configuration
public class BeanConfig {@LoadBalanced@Beanpublic RestTemplate getRestTemplate(){return new RestTemplate();}
}

在 RestTemplate 配置類上方, 使用 @LoadBalancerClient 或 @LoadBalancerClients 注解, 可以對不同的服務提供方配置不同的客戶端負載均衡算法策略,這樣就把默認的 輪詢策略替換成了 隨機策略

@LoadBalancerClient 注解說明

  1. name: 該負載均衡策略對哪個服務生效(服務提供方)。

  2. configuration : 該負載均衡策略用哪個負載均衡策略實現。

LoadBalancer 原理

LoadBalancer 的實現,主要是 LoadBalancerInterceptor ,這個類會對 RestTemplate 的請求進行攔截,然后從Eureka根據服務id獲取服務列表,隨后利用負載均衡算法得到真實的服務地址信息,替換服務id。

我們來看看源碼實現:

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {// ...@Overridepublic ClientHttpResponse intercept(final HttpRequest request,final byte[] body,final ClientHttpRequestExecution execution) throws IOException {URI originalUri = request.getURI();String serviceName = originalUri.getHost();
?Assert.state(serviceName != null,"Request URI does not contain a valid hostname: " + originalUri);
?return (ClientHttpResponse) this.loadBalancer.execute(serviceName,this.requestFactory.createRequest(request, body, execution));}
}

可以看到這里的intercept方法, 攔截了用戶的HttpRequest請求,然后做了幾件事:

  1. request.getURI() 從請求中獲取uri,也就是 http://product-service/product/1001

  2. originalUri.getHost() 從uri中獲取路徑的主機名,也就是服務id,product-service

  3. loadBalancer.execute 根據服務id,進行負載均衡,并處理請求。

public class BlockingLoadBalancerClient implements LoadBalancerClient {
?@Overridepublic <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {String hint = this.getHint(serviceId);
?LoadBalancerRequestAdapter<T, TimedRequestContext> lbRequest =new LoadBalancerRequestAdapter<>(request, this.buildRequestContext(request, hint));
?Set<LoadBalancerLifecycle> supportedLifecycleProcessors =this.getSupportedLifecycleProcessors(serviceId);
?supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
?// 根據 serviceId 和負載均衡策略選擇處理的服務ServiceInstance serviceInstance = this.choose(serviceId, lbRequest);
?if (serviceInstance == null) {supportedLifecycleProcessors.forEach(lifecycle -> {lifecycle.onComplete(new CompletionContext(Status.DISCARD, lbRequest, new EmptyResponse()));});throw new IllegalStateException("No instances available for " + serviceId);} else {return this.execute(serviceId, serviceInstance, lbRequest);}}
?/*** 根據 serviceId 和負載均衡策略選擇一個服務實例*/@Overridepublic <T> ServiceInstance choose(String serviceId, Request<T> request) {// 獲取負載均衡器ReactiveLoadBalancer<ServiceInstance> loadBalancer =this.loadBalancerClientFactory.getInstance(serviceId);
?if (loadBalancer == null) {return null;} else {// 根據負載均衡算法,在列表中選擇一個服務實例Response<ServiceInstance> loadBalancerResponse =(Response<ServiceInstance>) Mono.from(loadBalancer.choose(request)).block();
?return loadBalancerResponse == null ? null : loadBalancerResponse.getServer();}}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96573.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96573.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96573.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鴻蒙異步處理從入門到實戰:Promise、async/await、并發池、超時重試全套攻略

摘要&#xff08;介紹目前的背景和現狀&#xff09; 在鴻蒙&#xff08;HarmonyOS&#xff09;里&#xff0c;網絡請求、文件操作、數據庫訪問這類 I/O 都是異步的。主流寫法跟前端類似&#xff1a;Promise、async/await、回調。想把 app 做得“流暢且不阻塞”&#xff0c;核心…

【html2img/pdf 純!純!python將html保存為圖片/pdf!!效果非常的棒!】

素材 a.png html card.html <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><title>固定樣式卡片</title><style>/* 基礎樣式和頁面居中 */body {font-family: "微軟雅黑", "P…

帶寬評估(三)lossbase_v2

一、優化方向 調整丟包恢復算法的參數:可以通過調整算法中的一些參數,如丟包恢復速率、丟包恢復閾值等,來優化算法的性能。 調整發送窗口大小:在固定丟包場景下,可以通過調整發送窗口大小來控制發送速率,從而減少丟包率。 a=fmtp:96 x-google-min-bitrate=300 二、Goo…

imx6ull-驅動開發篇29——Linux阻塞IO 實驗

目錄 實驗程序編寫 blockio.c blockioApp.c Makefile 文件 運行測試 在之前的文章里&#xff0c;Linux阻塞和非阻塞 IO&#xff08;上&#xff09;&#xff0c;我們學習了Linux應用程序了兩種操作方式&#xff1a;阻塞和非阻塞 IO。 在Linux 中斷實驗中&#xff0c;Linux…

97. 小明逛公園,Floyd 算法,127. 騎士的攻擊,A * 算法

97. 小明逛公園Floyd 算法dijkstra, bellman_ford 是求單個起點到單個終點的最短路徑&#xff0c;dijkstra無法解決負權邊的問題&#xff0c; bellman_ford解決了負權邊的問題&#xff0c;但二者都是基于單起點和單終點。而Floyd 算法旨在解決多個起點到多個終點的最短路徑問題…

?崩壞世界觀中的安全漏洞與哲學映射:從滲透測試視角解構虛擬秩序的脆弱性?

?崩壞世界觀&#xff1a;游戲中的世界&#xff0c;是真實&#xff0c;也是虛幻的&#xff01;對于游戲中的NPC角色而言&#xff0c;TA們生存的世界&#xff0c;是真實的&#xff01;對于游戲玩家而言&#xff0c;游戲中的世界&#xff0c;是虛擬的&#xff01;通過沉浸式的游戲…

【離線安裝】CentOS Linux 7 上離線部署Oracle 19c(已成功安裝2次)

1.部署參考鏈接&#xff1a; CentOS 7 rpm方式離線安裝 Oracle 19chttps://blog.csdn.net/Vampire_1122/article/details/123038137?fromshareblogdetail&sharetypeblogdetail&sharerId123038137&sharereferPC&sharesourceweixin_45806267&sharefromfrom…

小白向:Obsidian(Markdown語法學習)快速入門完全指南:從零開始構建你的第二大腦(免費好用的筆記軟件的知識管理系統)、黑曜石筆記

一、認識Obsidian&#xff1a;不只是筆記軟件的知識管理系統 1.1 什么是Obsidian Obsidian是一個基于本地存儲的知識管理系統&#xff0c;它將你的所有筆記以純文本Markdown格式保存在電腦本地。這個名字來源于黑曜石——一種火山熔巖快速冷卻形成的玻璃質巖石&#xff0c;象…

攻防世界—Confusion1—(模板注入ssti)

一.解題在login和register的頁面中發現這個文件路徑接下去就找有什么點可以利用二.ssti通過題目信息可知是一只蛇把一只大象纏繞起來了&#xff0c;蛇代表python&#xff0c;大象代表php這邊通過python可以推測可能是模板注入&#xff0c;這邊我看其他的解題是說通過看報文信息…

【Protues仿真】基于AT89C52單片機的超聲波測距

目錄 1 HCSR04超聲波測距傳感器 1.1 基本參數 1.2 引腳說明 1.3 工作原理&#xff08;時序圖&#xff09; 2 基于AT89C52單片機的超聲波測距電路原理圖 2.1 硬件連接說明 2.2 工作原理 3 基于AT89C52單片機的超聲波測距控制程序 3.1.1 初始化設置 3.1.2 超聲波測距原…

LLM - Agent核心架構:四大“身體”部件

文章目錄一、Agent核心架構&#xff1a;四大“身體”部件1. 核心大腦&#xff1a;大型語言模型&#xff08;LLM&#xff09;2. 記憶系統&#xff1a;短期與長期記憶3. 工具箱&#xff08;Toolkit&#xff09;&#xff1a;從“思想家”到“行動家”4. 驅動循環&#xff08;Engin…

html-docx-js 導出word

2025.08.23今天我學習了如何將html頁面內容導出到word中&#xff0c;并保持原有格式&#xff0c;效果如下&#xff1a;代碼如下&#xff1a;1&#xff1a;列表頁面按鈕<el-button type"warning" plain icon"el-icon-download" size"mini" cli…

Science Robotics 通過人機交互強化學習進行精確而靈巧的機器人操作

機器人操作仍然是機器人技術中最困難的挑戰之一&#xff0c;其方法范圍從基于經典模型的控制到現代模仿學習。盡管這些方法已經取得了實質性進展&#xff0c;但它們通常需要大量的手動設計&#xff0c;在性能方面存在困難&#xff0c;并且需要大規模數據收集。這些限制阻礙了它…

Dism++備份系統時報錯[句柄無效]的解決方法

當使用Dism進行系統備份時遇到“[句柄無效]”的錯誤&#xff0c;這通常是由于某些文件或目錄的句柄無法正確訪問或已被占用所導致。以下是一種有效的解決方法&#xff1a;一、查看日志文件定位日志文件&#xff1a;首先&#xff0c;打開Dism軟件所在的目錄&#xff0c;并找到其…

華為/思科/H3C/銳捷操作系統操作指南

好的,這是一份針對 華為(VRP)、思科(IOS/IOS-XE)、H3C(Comware)和銳捷(Ruijie OS) 這四大主流網絡設備廠商操作系統的對比操作指南。本指南將聚焦于它們的共性和特性,幫助你快速掌握多廠商設備的基本操作。 四大網絡廠商操作系統綜合操作指南 一、 核心概念與模式對…

一文讀懂 DNS:從域名解析到百度訪問全流程

目錄 前言 一、什么是 DNS&#xff1f;—— 互聯網的 “地址簿” 為什么需要 DNS&#xff1f; DNS 的核心參數 二、DNS 解析原理&#xff1a;遞歸與迭代的協作 1. 兩種核心查詢方式 2. 完整解析流程&#xff08;以www.baidu.com為例&#xff09; 緩存清理命令 三、DNS …

初試Docker Desktop工具

文章目錄1. 概述2. 下載3. 安裝4. 注冊5. 登錄6. 啟動7. 容器8. 運行容器8.1 運行容器的鏡像8.2 獲取示例應用8.3 驗證Dockerfile文件8.4 拉取Alpine精簡鏡像8.5 創建鏡像8.6 運行容器8.7 查看前端9. 訪問靜態資源9.1 本地靜態資源9.2 創建服務器腳本9.3 修改Dockerfile文件9.4…

百度披露Q2財報:營收327億,AI新業務收入首超百億

8月20日&#xff0c;百度發布2025年第二季度財報&#xff0c;顯示季度總營收327億元&#xff0c;百度核心營收263億元&#xff0c;歸屬百度核心凈利潤74億元&#xff0c;同比增長35%。受AI驅動&#xff0c;涵蓋智能云在內的AI新業務收入增長強勁&#xff0c;首次超過100億元&am…

【字母異位分組】

思路 核心思路&#xff1a;使用排序后的字符串作為鍵&#xff0c;將原始字符串分組 鍵的選擇&#xff1a;對于每個字符串&#xff0c;將其排序后得到標準形式作為鍵分組存儲&#xff1a;使用哈希表&#xff0c;鍵是排序后的字符串&#xff0c;值是對應的原始字符串列表結果構建…

高防cdn如何緩存網頁靜態資源

為什么需要優化網頁靜態資源的緩存&#xff1f; 網頁靜態資源包括圖片、CSS、JavaScript等文件&#xff0c;它們通常體積大、訪問頻繁。在網頁訪問過程中&#xff0c;如果每次都從源服務器請求這些靜態資源&#xff0c;會導致網絡延遲和帶寬消耗。而優化網頁靜態資源的緩存&am…