Spring-Cloud 學習筆記-(4)負載均衡器Ribbon

目錄

  • Spring-Cloud 學習筆記-(4)負載均衡器Ribbon
  • 1、前言
  • 2、什么是負載均衡
    • 2.1、問題分析
    • 2.2、什么是Ribbon
  • 3、快速入門
    • 3.1、實現方式一
      • 3.1.1、修改代碼
    • 3.2、實現方式二
      • 3.2.1、啟動類
      • 3.2.2、調用代碼
      • 3.2.3、測試
      • 3.2.4、實現原理
      • 3.2.5、斷點調式
    • 3.3、修改輪詢策略
    • 3.4、重載機制
      • 3.4.1、為什么要有重載機制
      • 3.4.2、實現代碼

Spring-Cloud 學習筆記-(4)負載均衡器Ribbon

1、前言

  • 上個章節我們做了什么?

    上個章節我們說了用eureka來實現服務的注冊與發現,并且用過服務的seviceId拉取了服務列表List<ServiceInstance> instances = discoveryClient.getInstances("user-service") 從而實現服務的調用方(order-service)調用服務的提供方(user-service)

  • 本章節我們會做什么?

    負載均衡

2、什么是負載均衡

2.1、問題分析

? 上個章節我們實現了服務之間的調用,把原來代碼里面寫死的ip地址,換成用serviceId拉取服務列表,然后從服務列表中獲取實例的方式,雖然代碼變得復雜了,但是思想上我們得到的升級,但是還是存在一個問題,就是ServiceInstance instance = instances.get(0);每次我們都取同一個ip,要想每次使用不同的ip,我們自己就要寫負載均衡算法,從多個實例當中獲取某一個實例進行調用,這次我們這一章節講的就是負載均衡器Ribbon,它里面內置了很多負載均衡的算法,幫我們從實例列表中獲取一個實例。

2.2、什么是Ribbon

1441417-20181220002144278-1607410729.png

3、快速入門

我們按照上節課方法啟動,一個Eureka注冊中心,兩個(方便演示負載均衡)服務的提供方(user-service),最后我們修改服務調用方(order-service)代碼

pom文件

<!-- ribbon -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

3.1、實現方式一

3.1.1、修改代碼

    //注入  RibbonLoadBalancerClient@Autowiredprivate LoadBalancerClient client;
...//通過serviceId 拉取服務列表//List<ServiceInstance> instances = discoveryClient.getInstances("user-service");//ServiceInstance instance = instances.get(0);ServiceInstance instance = client.choose("user-service");
String jsonStr = restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"/api/v1/user/2", String.class);

之前我們是通過serviceId(“user-service”)獲取到的是服務列表,現在我們直接可以通過serviceId,返回的是單個實例,不是因為列表里面只有一個實例,是因為choose方法中已經幫我們做了復雜均衡了。

3.2、實現方式二

3.2.1、啟動類

/*** 把RestTemplate注入到Spring容器中*/
@Bean
@LoadBalanced //增加注解   讓RestTemplate內置一個負載均衡器
public RestTemplate restTemplate(){return new RestTemplate();
}

3.2.2、調用代碼

String jsonStr = restTemplate.getForObject("http://user-service/api/v1/user/2", String.class);

之前我們把serviceId交出去,別人幫我們取一堆,或者取一個,現在直接把serviceId寫在url路徑中。

3.2.3、測試

啟動order-service

訪問:http://localhost:8781/api/v1/order/2

1441417-20181220002156804-1047745316.png

3.2.4、實現原理

其實實現方式二低層就是用的實現方式一,只不過實現方式二加了一個攔截器LoadBalancerInterceptor對RestTemplate請求做了攔截,然后把請求路徑中的serviceId("user-service")拿到,然后通過方式一獲取某一個實例進行調用。

3.2.5、斷點調式

我們按兩下shift搜索到LoadBalancerInterceptor這個攔截器,在intercept方法中打好斷點

1441417-20181220002221036-307164370.png

public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {//1.拿到請求路徑URI originalUri = request.getURI();//2.從路徑中獲取serviceIdString serviceName = originalUri.getHost();Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);//3.執行execute方法.. 我們接著看execute方法return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}// RibbonLoadBalancerClient類中
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {//4.根據serviceId獲取到負載均衡器ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);//5.通過負載均衡器拿到某一個實例..我們接著看getServer方法Server server = this.getServer(loadBalancer);if (server == null) {throw new IllegalStateException("No instances available for " + serviceId);} else {RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));return this.execute(serviceId, ribbonServer, request);}}//RibbonLoadBalancerClient類中
protected Server getServer(ILoadBalancer loadBalancer) {//6.判斷負載均衡器是不是為空,不為空調用chooseServer("default")方法,我們接著看return loadBalancer == null ? null : loadBalancer.chooseServer("default");
}//BaseLoadBalancer類中
public Server chooseServer(Object key) {//這里key是默認值“default”if (this.counter == null) {this.counter = this.createCounter();}this.counter.increment();if (this.rule == null) {return null;} else {try {//根據rule調用choose方法,其中IRule是一個接口,有很多實現類,每一個實現類對于不同的負載均衡策略,比如RandomRule隨機,RoundRobinRule輪詢等,我們BaseLoadBalancer類中有一個屬性,   private static final IRule DEFAULT_RULE = new RoundRobinRule();代表默認輪詢策略,有興趣的可以看一下每一個實現的choose方法,比如輪詢策略RoundRobinRule,底層維護一個自增長的count,每調用一次count++,然后每次用count模于服務列表的長度(比如第一次:1%5=1,第二次:2%5=2)得到的值為服務列表的位置索引,從而實現輪詢。return this.rule.choose(key);} catch (Exception var3) {logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", new Object[]{this.name, key, var3});return null;}}}

3.3、修改輪詢策略

application.yml:

#--負載均衡輪詢策略 
# serviceId
user-service:ribbon:#負載均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

3.4、重載機制

3.4.1、為什么要有重載機制

在上一章中我們說到,一個正常的eureka客戶端,每間隔30秒沒有給服務器發送心跳,如果90秒服務器還沒有收到心跳,服務器就會認為這個客戶端已經宕機,但是eureka不會馬上剔除,沒間隔60會同意剔除這些失效的客戶端,這樣導致,我們服務實際上已經宕機了但是服務列表里面還有,這樣服務的消費者在調用的時候就會報錯,假設我們服務的提供方有五個,雖然只宕機了一臺,但是還有四臺是正常的,在這個時候我們條用這個服務如果出現報錯信息肯定不是我們希望看到的,所有我們就有了這個重載機制,Spring Cloud 整合了Spring Retry 來增強RestTemplate的重試能力,當一次服務調用失敗后,不會立即拋出一次,而是再次重試下一個服務。

3.4.2、實現代碼

application.yml

#服務名稱
spring:application:name: order-servicecloud:loadbalancer:retry:enabled: true # 開啟Spring Cloud的重試功能#負載均衡輪詢策略
user-service:ribbon:#負載均衡策略的classNameNFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRuleConnectTimeout: 250 # Ribbon的連接超時時間ReadTimeout: 1000 # Ribbon的數據讀取超時時間OkToRetryOnAllOperations: true # 是否對所有操作都進行重試MaxAutoRetriesNextServer: 1 # 切換實例的重試次數MaxAutoRetries: 1 # 對當前實例的重試次數

我們測試發現,就算我們user-service宕機了,也能通過另一臺服務實例獲取到結果!

轉載于:https://www.cnblogs.com/bigfly277/p/10147083.html

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

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

相關文章

‘仿微信發表朋友圈’項目中登錄功能的業務邏輯

登錄功能 手機號驗證碼都通過后端驗證后 返回用戶數據 登陸成功 成功后 調用store中的setUser方法 store中的setUser方法 將后端返回的用戶信息存儲到localStorage中 同時登錄成功后服務器會將token自動存入我們的cookie中 有過期時間 在我們請求需要登錄的接口時將cookie中的…

kubernetes--配置文件

轉載于:https://www.cnblogs.com/caiciadeliliang/p/10993388.html

微信動態中的背景圖更換

初衷&#xff1a; 圖一中的紅框中的部分&#xff0c;作為用戶自定義的背景圖&#xff0c;如果用戶沒有上傳也會為其自動設置一張背景圖&#xff0c;當用戶點擊時則會出現圖二中的選項 &#xff0c;點擊取消則選項消失&#xff0c;點擊從相冊選擇則會跳轉本機的相冊&#xff0c…

大數據學習——akka自定義RPC

實現 package cn.itcast.akkaimport akka.actor.{Actor, ActorSystem, Props} import akka.actor.Actor.Receive import com.typesafe.config.ConfigFactoryimport scala.collection.mutableimport scala.concurrent.duration._class Master(val host: String, val port: Int) …

從Client應用場景介紹IdentityServer4(一)

從Client應用場景介紹IdentityServer4&#xff08;一&#xff09; 原文:從Client應用場景介紹IdentityServer4&#xff08;一&#xff09;一、背景 IdentityServer4的介紹將不再敘述&#xff0c;百度下可以找到&#xff0c;且官網的快速入門例子也有翻譯的版本。這里主要從Clie…

開發常用代碼筆記

Vue 使用moment插件對時間進行格式化&#xff08;全局設置&#xff09; 下載插件 npm install moment --save 在main.js中引入插件 import moment from ‘moment’ 在main.js中定義全局過濾器 Vue.filter(dataFilter,function (dataStr,patten YYYY-MM-DD HH:mm:ss) {retur…

springboot 參數校驗詳解

https://www.jianshu.com/p/89a675b7c900 在日常開發寫rest接口時&#xff0c;接口參數校驗這一部分是必須的&#xff0c;但是如果全部用代碼去做&#xff0c;顯得十分麻煩&#xff0c;spring也提供了這部分功能,本文來探究一下如何實現 1.配置 spring-boot-starter-web包自動依…

微信小程序——賬號及開發工具

1. 注冊微信小程序賬號 點擊我進入微信公眾平臺 進入后點擊立即注冊 注冊成功且登錄后進入小程序管理后臺 2. 安裝開發者工具 點擊進入開發文檔 進入安裝開發工具&#xff08;穩定版本&#xff09; 一路默認下一步進行安裝 3. 開發者工具的使用 使用注冊微信小程序的微信號…

CSS注意的地方

content-box和border-box的區別 2018年02月27日 22:20:16 sulingliang 閱讀數&#xff1a;8011盒子模型 盒子寬度&#xff1a;paddingbordercontent-width 盒子高度&#xff1a;paddingbordercontent-height 如圖所示 盒子模型content-box 說明&#xff1a;在內容寬度和高度之…

機器學習筆記(6) 線性回歸

先從最簡單的例子開始,假設我們有一組樣本(如下圖的一個個黑色的圓點),只有一個特征,如下圖,橫軸是特征值,縱軸是label。比如橫軸是房屋面積,縱軸是房屋價格. 現在我們要做什么呢&#xff1f;我們試圖找到一條直線yaxb,可以盡量好的擬合這些點. 你可能要問了,為啥是直線,不是曲…

仿微信朋友圈項目梳理

項目功能簡介&#xff1a; 用戶通過手機號驗證碼進行登錄和注冊 可以瀏覽動態列表中的所有動態 登錄成功后用戶可以發表自己的動態 也可以對自己認可欣賞的動態進行點贊和評論 也可以通過動態結識志同道合的朋友 進行聊天和探討 前端&#xff1a;采用Vue框架搭建 weui進行頁面…

如何處理大流量高并發

1.動靜分離。 將網站中的靜態資源單獨拆分出來, 比如 css, js, 圖片, 視頻資源單獨存儲在一臺服務器上, 或者直接使用云存儲平臺, 七牛云或者阿里云之類的, 這樣能有效的降低主服務器的運行壓力 2.CDN加速。 云平臺提供 CDN 加速, 可以對資源進行全國服務器節點的分發, 提高全國…

echarts鼠標事件以及自定義數據獲取

事件添加方法&#xff1a; 對應官網位置&#xff1a;https://www.echartsjs.com/api.html#events 鼠標事件包括 click、dblclick、mousedown、mousemove、mouseup、mouseover、mouseout、globalout、contextmenu。 myChart.on(click, function (params) {console.log(params); …

[數學]點、線、面分割問題

平面分割問題 p條直線相交于一點時&#xff0c;分割的圖形有 2*(n-1) 個&#xff0c;此時再加一條直線&#xff0c;在 2*(n-1) 的基礎上再加 n條&#xff0c;此時為2*n n條曲線&#xff0c;其中有m條相交于一點&#xff0c;每兩個曲線都交于兩點 平面上有n條直線&#xff0c;且…

移動開發

1.移動端基礎 1.1 瀏覽器現狀 PC端瀏覽器 360瀏覽器、谷歌瀏覽器、火狐瀏覽器、QQ瀏覽器、百度瀏覽器&#xff08;停止服務&#xff09;、搜狗瀏覽器、IE瀏覽器 移動端瀏覽器 UC、QQ瀏覽器、歐朋瀏覽器、百度手機瀏覽器、360、搜狗、獵豹、谷歌等其他手機自帶的瀏覽器 國…

Django之路由系統

Django的路由系統 Django 1.11版本 URLConf官方文檔 URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL與要為該URL調用的視圖函數之間的映射表。 你就是以這種方式告訴Django&#xff0c;對于這個URL調用這段代碼&#xff0c;對于那個URL調用那段代碼。 URLconf配置…

微信小程序——操作數據庫

案例一&#xff1a;統計用戶的訪問次數 業務需求&#xff1a; 統計每個用戶對程序的訪問次數將訪問次數存儲到數據庫中訪問次數應該與用戶進行關聯 業務邏輯&#xff1a; 如果用戶是第一次訪問此程序&#xff0c;向數據庫添加一條記錄&#xff1a;{openid&#xff1a;45454…

shop--12.阿里云部署以及域名綁定

一、申請阿里云服務器&#xff08;1&#xff09;PC訪問阿里云https://www.aliyun.com/&#xff0c;申請阿里云帳號&#xff08;可以用您的支付寶帳號登錄&#xff0c;因為支付寶帳號已經進行了實名認證&#xff0c;使用起來更方便&#xff09;并登錄&#xff08;2&#xff09;找…

微信小程序——獲取用戶的運動步數

程序獲取用戶信息步驟 點擊參考微信文檔中的授權首先程序先向用戶申請訪問哪些權限用戶做出選擇后返回給程序程序攜帶權限訪問服務器如果用戶允許則返回信息如果用戶為允許則不返回 自定義函數getUserRun 為獲取用戶的微信運動數據 頁面加載調用此函數函數中執行下面操作 1…

C++之前置自增與后置自增

關于前置自增與后置自增的區別我是參考這里&#xff1a;http://bbs.bccn.net/thread-454977-1-1.html 簡單復述下&#xff0c;比如x; 與 x; 在C中&#xff0c;x這個表達式的值為原先x的值1&#xff0c;副作用是x的值增加了1&#xff1b;&#xff08;C中不是這樣定義的&#xff…