Ribbon負載均衡(四)


一、Ribbon定義

spring cloud Ribbon是基於Netflix Ribbon實現的一套客戶端,負載均衡工具

 

簡單的說,Ribbon是Netflix發布的開源項目,主要功能是提供客戶端的軟件負載均衡算法

,將Netflix的中間層服務層連接在一起.Ribbon客戶端組件提供一系列完善的配置項如連接

超時,重試等.簡單的說,就是在配置文件中列出Load Balancer(簡稱LB)后面所有的機器,

Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器.我們很容易使用Ribbon實現自定義的負載均衡算法

 ribbon原理圖:

 

二、LB負載均衡

集中式LB

即在服務的消費方和提供方之間使用獨立的LB設施(可以是硬件,比如F5,也可以是軟件,如Nginx)由該設施負責把訪問請求通過某一種策略轉發至服務的提供者;

進程式LB

將LB邏輯集成到消費方,消費方從服務中心獲取知有哪些地址可用,然后自己再從這些地址中選擇出一個合適的服務器.

Ribbon就屬於進程內LB,它只是一個類庫,集成於消費方進程,消費方通過他來獲取到服務提供方的地址.

三、官方地址

https://github.com/Netflix/ribbon

四、Ribbon的初始化配置

1、修改microservicecloud-consumer-dept-80工程 

修改pom文件

      <!-- 將微服務provider側注冊進eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

修改yml文件 添加

eureka:
  client:
    service-url:
      defaultZone:  http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #向服務中心注冊自己
    register-with-eureka: false 

對configBean進行新注解@LoadBalanced獲得Rest時加入Ribbon的配置

@Configuration public class ConfigBean { @Bean @LoadBalanced //注解表明這個restRemplate開啟負載均衡的功能。
    public RestTemplate getRestTemplate(){ return new RestTemplate(); } }

主啟動類ConSumeAppStart_80添加@EnableEurekaClient

@SpringBootApplication @EnableEurekaClient public class ConSumeAppStart { public static void main(String[] args) { SpringApplication.run(ConSumeAppStart.class); } }

修改DeptController客戶端訪問類

@RestController
public class DeptController {

    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
//完成真正的通過微服務名字從eureka上找到並訪問
    /**
     * 使用 使用restTemplate訪問restful接口非常的簡單粗暴無腦。 (url, requestMap,
     * ResponseBean.class)這三個參數分別代表 REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型。
     */
    @Autowired
    private RestTemplate restTemplate;
    @RequestMapping(value = "/consumer/dept/add")
    public boolean add(Dept dept)
    {
        return restTemplate.postForObject(REST_URL_PREFIX + "/dept/addDept", dept, Boolean.class);
    }

    @RequestMapping("/findAll")
    public List<Dept> findAll() {
        return restTemplate.getForObject(REST_URL_PREFIX + "/dept/findAll",List.class);
    }
}

先啟動3個eureka集群后,在啟動microservicecloud-config-dept-client-8001並注冊進eureka

啟動ConSumeAppStart_80

測試 訪問地址:http://localhost:80/findAll

效果

 

五、Ribbon負載均衡

1、架構說明圖

 

Ribbon在工作分成2步

 第一步:先選擇EurekaServer,它優先選擇在同一個區域負載較少的server

第二步:再根據用戶指定策略,在從server取到的服務注冊列表中選擇一個地址.

其中Ribbon提供了多種策略:比如輪詢,隨機和根據時間響應加權

 六、創建提供者多服務

參考microservicecloud-provider-dept-8001新建2份,分別命名為8002,8003  

新建8002/8003 數據庫,各自微服務分別連各自的數據庫clouddb02/clouddb03

修改8002/8003各自的yml

8002 yml

server: port: 8002 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑 type-aliases-package: com.yehui.entity # 所有Entity別名類所在包 mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件 #應用名稱 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://localhost:3306/clouddb02 # 數據庫名稱 username: root password: root dbcp2: min-idle: 5 # 數據庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/ ###是否向注冊中心注冊自己 register-with-eureka: true ###是否需要從eureka上獲取注冊信息 fetch-registry: true instance: instance-id: providerdept_8001 #自定義服務名稱 prefer-ip-address: true #訪問路徑可以顯示IP地址 #信息的描述 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$

 8003yml

server: port: 8003 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路徑 type-aliases-package: com.yehui.entity # 所有Entity別名類所在包 mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件 spring: application: name: microservicecloud-dept datasource: type: com.alibaba.druid.pool.DruidDataSource # 當前數據源操作類型 driver-class-name: org.gjt.mm.mysql.Driver # mysql驅動包 url: jdbc:mysql://localhost:3306/clouddb03 # 數據庫名稱 username: root password: root dbcp2: min-idle: 5 # 數據庫連接池的最小維持連接數 initial-size: 5 # 初始化連接數 max-total: 5 # 最大連接數 max-wait-millis: 200 # 等待連接獲取的最大超時時間 eureka: client: #客戶端注冊進eureka服務列表內 service-url: defaultZone: http://localhost:7002/eureka/,http://localhost:7003/eureka/,http://localhost:7001/eureka/ instance: instance-id: providerdept_8003 #自定義服務名稱 prefer-ip-address: true #訪問路徑可以顯示IP地址 #信息的描述 info: app.name: atguigu-microservicecloud company.name: www.atguigu.com build.artifactId: $project.artifactId$ build.version: $project.version$

備注  

   端口

數據庫鏈接  jdbc:mysql://localhost:3306/clouddb01

對外暴露的統一的服務實例名

 

啟動3個eureka集群配置區

啟動3個Dept微服務並各自測試通過

 

http://localhost:8003/dept/findAll

http://localhost:8001/dept/findAll

http://localhost:8002/dept/findAll

 

啟動ConSumeAppStart_80

客戶端通過Ribbon完成負載均衡並訪問上一步的Dept微服務

 

上圖有三個消費者

 

http://localhost/findAll

注意觀察看到返回的數據的數據庫的不同

 

從上面可以得到:Ribbon其實就是一個軟負載均衡的客戶端組件,他可以和其他所需求請求的客戶端結合使用,eureka結合只是其中的一個實例

七、Ribbon核心組件IRule

1、IRule算法

IRule:根據特點算法中從服務列表中選取一個要訪問的服務

RoundRobinRule:輪詢算法

RandomRule隨機算法

AvailabilityFilteringRule:會先過濾由於多次訪問故障而處於斷路器跳閘狀態的服務,還有並發的連接數量超過閾值的服務,然后對剩余的服務列表按照輪詢策略進行訪問

WeightedResponseTimeRule:根據平均響應的時間計算所有服務的權重,響應時間越快服務權重越大被選中的概率越高,剛啟動時如果統計信息不足,則使用RoundRobinRule策略,等統計信息足夠會切換到WeightedResponseTimeRule

RetryRule:先按照RoundRobinRule的策略獲取服務,如果獲取失敗則在制定時間內進行重試,獲取可用的服務。

BestAviableRule:會先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的服務

ZoneAvoidanceRule:默認規則,符合判斷server所在區域的性能和server的可用性選擇服務器

RetryRule:先根據RoundRonbinRule的策略獲取服務,如果獲取服務失敗則在指定時間內會進行重試,獲取可用的服務

訪問地址:https://github.com/Netflix/ribbon

 

 config類

@Bean
public IRule getRule(){
    return new RandomRule(); //使用隨機的算法替換默認的輪詢算法
}

測試訪問:http://localhost:80/findAll

 2、Ribbon自定義

修改microservicecloud-consumer-dept-80

 

主啟動類添加@RibbonClient

在啟動該微服務的時候就能去加載我們自定義Ribbon配置類,從而使配置生效,形如:

@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MyRule.class)

注意細節

步驟:

  新建一個MyRule類

@Configuration public class MyRule { @Bean public IRule getRule(){ return new RoundRobinRule(); //使用使用輪詢算法
 } }

  修改主啟動類新增@RibbonClient注解

@SpringBootApplication @EnableEurekaClient //表明自己是一個eurekaclient.
@RibbonClient(name = "MICROSERVICECLOUD-DEPT",configuration = MyRule.class) public class ConSumeAppStart_80 { public static void main(String[] args) { SpringApplication.run(ConSumeAppStart_80.class); } }

 測試http://localhost:80/findAll

3、自定義規則深度解析

問題:依舊輪詢策略,但是加上新需求,每個服務要求被調用5次.也即

以前是每台機器一次,現在是每台機器5次

解析源碼:https://github.com/Netflix/ribbon/blob/master/ribbon-

loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

參考源碼修改為我們的需求需的MyRole_YH.java

 更新中

4、使用DiscoveryClient實現本地負載均衡

編寫controller

@RestController public class DeptController { //獲取服務注冊信息
 @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @RequestMapping("/find") public List<Dept> find(){ List<ServiceInstance> instances = discoveryClient.getInstances("microservicecloud-dept"); int instacesSize = instances.size(); int index = num%instacesSize; num++; String url = instances.get(index).getUri().toString(); return restTemplate.getForObject(url + "/dept/findAll",List.class); } } 

congig類

@Configuration public class ConfigBean { @Bean //@LoadBalanced 這個注解不需要了
    public RestTemplate getRestTemplate(){ return new RestTemplate(); } }

測試

5、Ribbon與Nginx區別

客戶端負載均衡器

 在SpringCloud中Ribbon負載均衡客戶端,會從eureka注冊中心服務器端上獲取服務注冊信息列表,緩存到本地。

讓后在本地實現輪訓負載均衡策略。

服務器端負載均衡Nginx

 nginx是客戶端所有請求統一交給nginx,由nginx進行實現負載均衡請求轉發,屬於服務器端負載均衡。

 既請求有nginx服務器端進行轉發。

客戶端負載均衡Ribbon

 Ribbon是從eureka注冊中心服務器端上獲取服務注冊信息列表,緩存到本地,讓后在本地實現輪訓負載均衡策略。

 既在客戶端實現負載均衡。

 應用場景的區別:

Nginx適合於服務器端實現負載均衡 比如Tomcat ,Ribbon適合與在微服務中RPC遠程調用實現本地服務負載均衡,比如Dubbo、SpringCloud中都是采用本地負載均衡。

 


免責聲明!

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



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