Spring Cloud之負載均衡之LoadBalance

目錄

負載均衡

問題

步驟

現象?

什么是負載均衡?

負載均衡的一些實現

服務端負載均衡

客戶端負載均衡

使用Spring Cloud LoadBalance實現負載均衡

負載均衡策略

?編輯??編輯LoadBalancer原理

服務部署

準備環境和數據

服務構建打包

啟動服務

上傳Jar包到云服務器

啟動服務

遠程調用訪問?


負載均衡

問題

上面是我們之前的代碼,是根據應用名稱獲取了服務實例列表,并從列表中選擇了一個服務實例。

那如果一個服務對應多個實例呢?流量是否可以合理的分配到多個實例呢?

我們再啟動兩個product-service示例。

步驟

打開View->Tool Windows->Services

選中ProductServiceApplication,然后右鍵,選擇Copy Configuration

然后改名,并點擊Modify options

然后點擊Add VM options

然后添加-Dserver.port=9091,然后Apply,OK

然后再重復上述步驟,再添加一個服務實例。

現象?

啟動上述所有實例后,可以在Eureka網站頁面看到:

此時多次訪問"http://127.0.0.1:8080/order/1",然后查看IDEA上的日志,可以看到,我們剛剛的多次訪問,都訪問到了同一臺機器上,即第一個注冊到Eureka的服務實例端口號為9092的機器。

這肯定不是我們想要的結果,我們啟動多個服務實例,是希望可以分擔其它機器的負荷,那么如何實現呢?

我們可以修改一下之前的order-service中的OrderService代碼,把只請求服務列表第一臺機器修改為輪詢請求服務列表中的機器。

修改后的order-service中的OrderService代碼如下:

package order.service;import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import order.mapper.OrderMapper;
import order.model.OrderInfo;
import order.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;//計數器private AtomicInteger count = new AtomicInteger(1);private List<ServiceInstance> instances;@PostConstructpublic void init(){//從Eureka中獲取服務列表instances = discoveryClient.getInstances("product-service");}public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);//計算輪流的實例idnexint index= count.getAndIncrement() % instances.size();//獲取實例String uri = instances.get(index).getUri().toString();//拼接urlString url = uri+"/product/"+orderInfo.getProductId();log.info("遠程調用url:{}", url);ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}}

重啟order-service,再次多次訪問"127.0.0.1:8080/order/1",可以看到每個服務實例都有被請求到:

通過?志可以看到, 請求被均衡的分配在了不同的實例上, 這就是負載均衡.

什么是負載均衡?

負載均衡(Load Balance,簡稱 LB) , 是?并發, ?可?系統必不可少的關鍵組件.
當服務流量增?時, 通常會采?增加機器的?式進?擴容, 負載均衡就是?來在多個機器或者其他資源中, 按照?定的規則合理分配負載.

負載均衡的一些實現

上?的例?中, 我們只是簡單的對實例進?了輪詢, 但真實的業務場景會更加復雜. ?如根據機器的配置進?負載分配, 配置?的分配的流量?, 配置低的分配流量低等.

服務多機部署時, 開發?員都需要考慮負載均衡的實現, 所以也出現了?些負載均衡器, 來幫助我們實現負載均衡.

負載均衡分為服務端負載均衡和客?端負載均衡.

服務端負載均衡

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

客戶端負載均衡

在客?端進?負載均衡的算法分配.

把負載均衡的功能以庫的?式集成到客?端, ?不再是由?臺指定的負載均衡設備集中提供.
?如Spring Cloud的Ribbon, 請求發送到客?端, 客?端從注冊中?(?如Eureka)獲取服務列表, 在發送請求前通過負載均衡算法選擇?個服務器,然后進?訪問.
Ribbon是Spring Cloud早期的默認實現, 由于不維護了, 所以最新版本的Spring Cloud負載均衡集成的是Spring Cloud LoadBalancer(Spring Cloud官?維護)。

客?端負載均衡和服務端負載均衡最?的區別在于服務清單所存儲的位置。

Spring Cloud LoadBalance

SpringCloud 從 2020.0.1 版本開始, 移除了Ribbon 組件,使?Spring Cloud LoadBalancer 組件來代替 Ribbon 實現客?端負載均衡。

使用Spring Cloud LoadBalance實現負載均衡

1. 給 RestTemplate 這個Bean添加 @LoadBalanced 注解就可以

package order.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}

2.修改后的order-service中的OrderService代碼如下:

修改IP為服務端名稱。

package order.service;import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import order.mapper.OrderMapper;
import order.model.OrderInfo;
import order.model.ProductInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Slf4j
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public OrderInfo selectOrderById(Integer orderId){OrderInfo orderInfo = orderMapper.selectOrderById(orderId);String url = "http://product-service/product/"+orderInfo.getProductId();log.info("遠程調用url:{}", url);ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);orderInfo.setProductInfo(productInfo);return orderInfo;}
}

此時再次多次訪問"127.0.0.1:8080/order/1",可以看到每個服務實例都有被請求到,且比例差不多:

負載均衡策略

負載均衡策略是?種思想, ?論是哪種負載均衡器, 它們的負載均衡策略都是相似的. Spring Cloud
LoadBalancer 僅?持兩種負載均衡策略: 輪詢策略 和 隨機策略。

1. 輪詢(Round Robin): 輪詢策略是指服務器輪流處理??的請求. 這是?種實現最簡單, 也最常?的策略. ?活中也有類似的場景, ?如學校輪流值?, 或者輪流打掃衛?.
2. 隨機選擇(Random): 隨機選擇策略是指隨機選擇?個后端服務器來處理新的請求.

官方介紹

翻譯:

Spring Cloud提供了自己的客戶端負載均衡器抽象和實現。對于負載平衡機制,添加了ReactiveLoadBalancer接口,并為其提供了基于輪轉和隨機的實現。為了讓實例從反應式ServiceInstanceListSupplier中進行選擇,使用了該接口。目前,我們支持ServiceInstanceListSupplier的基于服務發現的實現,該實現使用類路徑中可用的發現客戶端從服務發現中檢索可用實例。通過將Spring.Cloud.LoadBalancer.enabled的值設置為false,可以禁用Spring Cloud LoadBalancer。

1. 定義隨機算法對象, 通過 @Bean 將其加載到 Spring 容器中
此處使?Spring Cloud LoadBalancer提供的 RandomLoadBalancer

package order.config;import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;public class CustomLoadBalancerConfiguration {@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. 在組件掃描范圍內?

2. 使? @LoadBalancerClient 或者 @LoadBalancerClients 注解

在 RestTemplate 配置類上?, 使? @LoadBalancerClient 或 @LoadBalancerClients 注解, 可以對不同的服務提供?配置不同的客?端負載均衡算法策略.
由于我們只有?個客戶端服務提供者, 所以使?@LoadBalancerClient。

package order.config;import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@LoadBalancerClient(name = "product-service", configuration = CustomLoadBalancerConfiguration.class)
@Configuration
public class BeanConfig {@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}
}

@LoadBalancerClient 注解說明
1. name: 該負載均衡策略對哪個服務?效(服務提供?)
2. configuration : 該負載均衡策略 ?哪個負載均衡策略實現.?

此時再次多次訪問"127.0.0.1:8080/order/1",可以看到每個服務實例都有被請求到,且比例隨機:

?LoadBalancer原理

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

我們來看看源碼實現:

可以看到這?的intercept?法, 攔截了??的HttpRequest請求,然后做了?件事:

1. request.getURI() 從請求中獲取uri, 也就是 http://product-service
2. service/product/1001 originalUri.getHost() 從uri中獲取路徑的主機名, 也就是服務id, product-service
3. loadBalancer.execute 根據服務id, 進?負載均衡, 并處理請求?

根據serviceId,和負載均衡策略, 選擇處理的服務:?

?根據serviceId,和負載均衡策略, 選擇處理的服務:

服務部署
準備環境和數據

安裝好JDK17和MySQL,并在MySQL中建表且存放好數據信息。

修改配置文件中的數據庫密碼。

服務構建打包

采?Maven打包, 需要對3個服務分別打包:
eureka-server, order-service, product-service

啟動服務
上傳Jar包到云服務器

第一次上傳需要安裝 lrzsz

Centos:

yum install lrzsz

Ubantu:

apt install lrzsz?

直接拖動文件到xshell窗口,上傳成功。

啟動服務

#后臺啟動eureka-server, 并設置輸出?志到logs/eureka.log
nohup java -jar eureka-server.jar >logs/eureka.log &


#后臺啟動order-service, 并設置輸出?志到logs/order.log
nohup java -jar order-service.jar >logs/order.log &


#后臺啟動product-service, 并設置輸出?志到logs/order.log
nohup java -jar product-service.jar >logs/product-9090.log &

再多啟動兩臺product-service實例

#啟動實例, 指定端?號為9091
nohup java -jar product-service.jar --server.port=9091 >logs/product-9091.log &


#啟動實例, 指定端?號為9092
nohup java -jar product-service.jar --server.port=9092 >logs/product-9092.log &?

遠程調用訪問?

可以看到,能夠正常訪問并響應。

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

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

相關文章

數據無憂:自動備份策略全解析

引言 在信息化飛速發展的今天&#xff0c;數據已成為個人、企業乃至國家最為寶貴的資產之一。無論是日常辦公文檔、科研數據、客戶資料&#xff0c;還是個人隱私信息&#xff0c;一旦丟失或損壞&#xff0c;都可能帶來不可估量的損失。因此&#xff0c;備份文件作為數據安全的…

Latex2024安裝教程(附安裝包)Latex2024詳細圖文安裝教程

文章目錄 前言一、Latex2024下載二、Texlive 2024安裝教程1.準備安裝文件2.啟動安裝程序3.配置安裝選項4.開始安裝5.安裝完成6.TeX Live 2024 安裝后確認 三、Texstudio 安裝教程1.準備 Texstudio 安裝2.啟動 Texstudio 安裝向導3.選擇安裝位置4.等待安裝完成5.啟動 Texstudio6…

C++ 語法之函數和函數指針

在上一章中 C 語法之 指針的一些應用說明-CSDN博客 我們了解了指針變量&#xff0c;int *p;取變量a的地址這些。 那么函數同樣也有個地址&#xff0c;直接輸出函數名就可以得到地址&#xff0c;如下&#xff1a; #include<iostream> using namespace std; void fun() …

centos【rockylinux】安裝【supervisor】的注意事項【完整版】

重新加載 systemd 配置推薦使用pip的方式安裝 pip install supervisor 第二步&#xff1a;添加supervisord.conf配置文件 [unix_http_server] file/tmp/supervisor.sock ; UNIX socket 文件&#xff0c;supervisorctl 會使用 ;chmod0700 ; socket 文件的…

Spring Cloud Gateway 使用ribbon以及nacos實現灰度發布

1、Spring Cloud Gateway配置文件 gateway:userId-limit: 1000 agent-bff:ribbon:NFLoadBalancerRuleClassName: com.anlitech.gateway.gray.GrayRule operator-bff:ribbon:NFLoadBalancerRuleClassName: com.anlitech.gateway.gray.GrayRule spring:cloud:gateway:locator:en…

關于“碰一碰發視頻”系統的技術開發文檔框架

以下是關于“碰一碰發視頻”系統的技術開發文檔框架&#xff0c;涵蓋核心功能、技術選型、開發流程和關鍵模塊設計&#xff0c;幫助您快速搭建一站式解決方案 --- 隨著短視頻平臺的興起&#xff0c;用戶的創作與分享需求日益增長。而如何讓視頻分享更加便捷、有趣&#xff0c…

基于django+vue的購物商城系統

開發語言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.8數據庫&#xff1a;mysql 5.7數據庫工具&#xff1a;Navicat11開發軟件&#xff1a;PyCharm 系統展示 系統首頁 熱賣商品 優惠資訊 個人中心 后臺登錄 管理員功能界面 用戶管理 商品分類管理…

Ardunio 連接OLED觸摸屏(SSD1106驅動 4針 IIC通信)

一、準備工作 1、硬件 UNO R3 &#xff1a;1套 OLED觸摸屏&#xff1a;1套 導線諾干 2、軟件 arduino 二、接線 UNO R3OLED5VVCCGNDGNDA5SCLA4SDA 腳位如下圖所示&#xff1a; Uno R3腳位圖 觸摸屏腳位圖 查閱顯示屏的驅動規格&#xff1a;通常顯示屏驅動芯片有SSD1306,SH110…

機器人技能列表

一、機器人制作基礎入門 &#xff08;一&#xff09;機器人概述 1.機器人的定義與分類 2.機器人的發展歷程與現狀 3.機器人在各領域的應用案例 &#xff08;二&#xff09;必備工具與材料 4.常用電子工具介紹&#xff08;萬用表、電烙鐵等&#xff09; 5.機械加工工具&…

07. 面向對象高級(2)_設計模式

什么是設計模式 一個問題通常有種解法&#xff0c;其中肯定有一種解法是最優的&#xff0c;這個最優的解法被人總結出來了&#xff0c;稱之為設計模式。 設計模式有20多種&#xff0c;對應20多種軟件開發中會遇到的問題。 關于設計模式&#xff0c;主要學什么&#xff1f; 解…

【面試場景題-Redis中String類型和map類型的區別】

今天在面試中碰到一個場景題&#xff1a;在 Redis 中存儲 100 萬用戶數據時&#xff0c;使用 String 類型和 Hash&#xff08;Map&#xff09;類型的主要區別是什么&#xff1f;體現在以下幾個方面&#xff1a; 1. 存儲結構與內存占用 String 類型 存儲方式&#xff1a;每個用…

計算機操作系統和進程

目錄 一. 操作系統 1. 操作系統的概念 2. 操作系統的功能 二. 進程 1. 進程的概念 2. 進程在系統中的管理 3. PBC &#xff08;1&#xff09;pid &#xff08;2&#xff09;內存指針 &#xff08;3&#xff09;文件標識符 4. 資源分配 5. 進程的調度 &#xff08;…

【Matlab GUI】封裝matlab GUI為exe文件

注&#xff1a;封裝后的exe還是需要有matlab環境才能運行 &#xff08;1&#xff09;安裝MCRinstaller.exe文件&#xff0c;在matlab安裝目錄下的toolbox/compiler/deploy/win64文件夾里 &#xff08;2&#xff09;安裝完MCRinstaller.exe&#xff0c;字命令窗口輸入&#x…

登山第二十梯:無人機實時自主探索——我是一只小小小鳥

文章目錄 一 摘要 二 資源 三 內容 一 摘要 自主探索是無人機 &#xff08;UAV&#xff09; 各種應用的基本問題。最近&#xff0c;基于 LiDAR 的探索因其能夠生成大規模環境的高精度點云地圖而受到廣泛關注。雖然點云本身就為導航提供了信息&#xff0c;但許多現有的勘探方…

JAVA序列化與反序列化URLDNS鏈CC1鏈

1、序列化的實現 java序列化的是對象屬性的&#xff0c;只有實現了Serializable或者Externalizable接口的類的對象才能被序列化為字節序列。&#xff08;不是則會拋出異常&#xff09;&#xff0c;靜態成員變量是屬于類的&#xff0c;所以靜態成員變量是不能被序列化的&#x…

SAP-ABAP: 采購申請創建(PR)BAPI_PR_CREATE 技術指南-詳解

BAPI_PR_CREATE 技術指南 用途&#xff1a;通過 RFC 接口創建 SAP 采購申請&#xff08;PR&#xff09;&#xff0c;支持自動化集成與批量處理。 一、功能概覽 類別說明核心功能創建標準采購申請、預留轉采購申請&#xff0c;支持多行項目及賬戶分配。集成場景與 MRP 系統、外…

Android7 Input(一)Android Input服務初始化

本系列博客主要描述Android 7.1系統中輸入管理服務InputManagerService的源碼分析。 概述 本文主要描述了InputManagerService服務的初始化和啟動&#xff0c;在Android7系統上InputManagerService服務的框架如下所示: 注&#xff1a;箭頭的方向&#xff0c;并不能真實代表數…

用于 RGB-D 顯著目標檢測的點感知交互和 CNN 誘導的細化網絡(問題)

摘要 問題一&#xff1a;但在對自模態和跨模態的全局長距離依賴關系進行建模方面仍顯不足。什么意思&#xff1f; 自模態&#xff08;Intra-modal&#xff09;全局依賴&#xff1a;在同一模態內&#xff0c;長距離像素之間的信息交互對于理解全局背景很重要&#xff0c;但 CN…

html5基于Canvas的經典打磚塊游戲開發實踐

基于Canvas的經典打磚塊游戲開發實踐 這里寫目錄標題 基于Canvas的經典打磚塊游戲開發實踐項目介紹技術棧核心功能實現1. 游戲初始化2. 游戲對象設計3. 碰撞檢測系統4. 動畫系統5. 用戶界面設計 性能優化1. 渲染優化2. 內存管理 項目亮點技術難點突破項目總結 項目介紹 在這個…

MySQL外鍵約束下的索引刪除難題:從報錯到完美解決的實戰指南

&#x1f6a8; MySQL外鍵約束下的索引刪除難題&#xff1a;從報錯到完美解決的實戰指南 &#x1f525; 問題背景&#xff1a;一個看似簡單的刪除操作引發的連環坑 場景復現&#xff1a;某日接到需求&#xff0c;需刪除 invite_codes 表中的冗余索引 FKnqn27fyjlgio5y60eieohi0…