eureka服務注冊與負載均衡原理


一、首先第一步,搭建eureka-server (注冊中心服務端),這是一個獨立的微服務

  1、在微服務的父工程下,新建一個maven項目作為eureka服務端的項目

  2、在項目中的pom文件中引入eureka服務端的依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

  3、編寫啟動類,注意啟動類上要加上@EnableEurekaServer注解,開啟eureka的注冊中心功能

  

@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class, args); } }

  4、在application.yml配置文件中書寫配置

      包括:配置服務端口號、配置服務名稱、配置eureka的地址信息(eureka自己也是一個微服務,他會把自己也注冊到eureka中)

server:
  port: 10086
spring:
  application:
    name: eureka-server
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka

  5、接下來就可以啟動項目啦,到瀏覽器中訪問地址 http://127.0.0.1:10086 出現eureka的圖形界面就成功了

 

 

二、服務注冊(將拆分的所有微服務注冊到eureka中,讓eureka來進行管理)

  1、引入客戶端依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

  2、編寫application.yml配置文件

    配置信息包括:同樣包括三個基本的配置: 服務端口、服務名稱、服務地址信息

spring:
  application:
    name: userservice
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka

 

 

三、服務拉取和負載均衡

  之前我們服務調用服務是這么做的,服務請求地址是寫死的,這樣一個服務有多個實例的話就無法實現負載均衡了

@Resource private RestTemplate restTemplate; @GetMapping("{orderId}") public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) { // 根據id查詢訂單並返回
        Order order = orderService.queryOrderById(orderId); //定義請求的路徑
        String url = "http://127.0.0.1:8081/user/"+order.getUserId(); //發送get請求
        User user = restTemplate.getForObject(url, User.class); order.setUser(user); return order; }

  現在我們將請求地址進行如下改寫,用服務名稱代替IP地址和端口號

String url = "http://userservice/user/"+order.getUserId();

  服務提供者如果有多個實例的話,還需要實現負載均衡,在restTemplate組件上添加一個 @LoadBalanced 注解即可實現

  完成此操作后,spring會自動幫助我們從eureka-server端,根據userservice這個服務名稱,獲取實例列表,而后完成負載均衡。

@Bean @LoadBalanced public RestTemplate restTemplate(){ return new RestTemplate(); }

 

四、負載均衡的實現原理細節

  1、問題:我們添加了@LoadBalanced注解,即可實現負載均衡功能,這是什么原理呢?

 

2、springcloud底層利用了一個名為Ribbon的組件來實現的負載均衡的功能

 

 

 

             

3、源碼跟蹤:核心類 LoadBalancerIntercepor,感興趣的小伙伴可以以此為入口,進行源碼解讀

 

4、總結:SpringCloudRibbon的底層采用了一個攔截器,攔截了RestTemplate發出的請求,對地址做了修改。用一幅圖來總結一下:

 

 

              

 

 

5、基本流程如下:( 這里模擬訂單服務需要請求用戶服務 )

  • 攔截我們的RestTemplate請求http://userservice/user/1

  • RibbonLoadBalancerClient會從請求url中獲取服務名稱,也就是userservice

  • DynamicServerListLoadBalancer根據userservice到eureka拉取服務列表

  • eureka返回列表,localhost:8081、localhost:8082

  • IRule利用內置負載均衡規則,從列表中選擇一個,例如localhost:8081

  • RibbonLoadBalancerClient修改請求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,發起真實請求

6、上面提到一個負載均衡規則概念:那到底有哪些負載均衡的規則呢,如何實現的呢?我們可以自定義規則嗎?

  負載均衡的規則都定義在IRule接口中,而IRule有很多不同的實現類:

            

 

  6.1 不同規則的含義如下所示:

內置負載均衡規則類 規則描述
RoundRobinRule 簡單輪詢服務列表來選擇服務器。它是Ribbon默認的負載均衡規則。
AvailabilityFilteringRule 對以下兩種服務器進行忽略: (1)在默認情況下,這台服務器如果3次連接失敗,這台服務器就會被設置為“短路”狀態。短路狀態將持續30秒,如果再次連接失敗,短路的持續時間就會幾何級地增加。 (2)並發數過高的服務器。如果一個服務器的並發連接數過高,配置了AvailabilityFilteringRule規則的客戶端也會將其忽略。並發連接數的上限,可以由客戶端的<clientName>.<clientConfigNameSpace>.ActiveConnectionsLimit屬性進行配置。
WeightedResponseTimeRule 為每一個服務器賦予一個權重值。服務器響應時間越長,這個服務器的權重就越小。這個規則會隨機選擇服務器,這個權重值會影響服務器的選擇。

ZoneAvoidanceRule

(默認的)

以區域可用的服務器為基礎進行服務器的選擇。使用Zone對服務器進行分類,這個Zone可以理解為一個機房、一個機架等。而后再對Zone內的多個服務做輪詢。
BestAvailableRule                 忽略那些短路的服務器,並選擇並發數較低的服務器。
RandomRule 隨機選擇一個可用的服務器。
RetryRule 重試機制的選擇邏輯

 

   6.2 自定義負載均衡策略

    通過定義IRule實現可以修改負載均衡的規則,有兩種方式:

    方式一:在配置類中注冊一個IRule組件,注冊需要的規則,這種規則全局生效

@Bean public IRule randomRule(){ return new RandomRule(); }

    方式二: 在服務消費者的application.yml配置文件中添加如下配置:(具體針對某一個服務生效)

userservice: #給某個微服務配置負載均衡規則,這里是是服務名稱 ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #負載均衡規則,這里是隨機訪問

    注意,一般用默認的負載均衡規則,不做修改。

 

7、飢餓加載 

  Ribbon默認是采用懶加載,即第一次訪問時才會去創建LoadBalanceClient,請求時間會很長。

  而飢餓加載則會在項目啟動時創建,降低第一次訪問的耗時,通過在服務消費者配置文件中添加下面配置開啟飢餓加載:

ribbon:
  eager-load:
    enabled: true
    clients: userservice  #服務提供者的服務名稱

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM