【分佈式】SpringCloud(4)--Ribbon負載均衡

1.Ribbon概述

1.1.Ribbon是什麼

SpringCloud Ribbon是基於Netflix Ribbon實現的一套基於客戶端Client的負載均衡工具mysql

Ribbon主要的功能是提供客戶端的軟件負載均衡算法,將Netflix的中間層服務鏈接在一塊兒,提供一系列完善的配置項如鏈接超時、重試等。nginx

簡單地說,就是在配置文件中列出Load Balancer(LB)後面全部的機器,Ribbon會自動地幫助你基於某種規則(如簡單輪詢、隨機鏈接等)去鏈接這些機器。git

 

1.2.負載均衡LB分類

集中式LB:github

在服務的消費方和提供方之間使用獨立的LB設施(能夠是硬件(F5),也能夠是軟件(nginx)),由這些設施負責把訪問請求經過某種策略轉發至服務的提供方。(至關於公務員考公,國家選舉)算法

進程內LB:spring

將LB的邏輯集成到消費方,消費方從服務註冊中心獲知有哪些地址可用,而後本身在從這些地址中選擇出一個合適的服務器。(至關於客戶點餐選擇人少的取餐點取餐)sql

 

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

 

2.Ribbon 客戶端配置

2.1.pom.xml

 <!--引入Ribbon相關:ribbon->eureka->config-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-ribbon</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
  </dependency>
  <!--微服務provider方引入eureka-->
  <dependency>
      <groupId>org.springframework.cloud</groupId>
      <!--沒有帶sever表示就是client客戶端-->
      <artifactId>spring-cloud-starter-eureka</artifactId>
      <version>1.4.6.RELEASE</version>
  </dependency>

 

2.2.application.yml

server:
#80端口被佔用,選擇了81測試
port: 81

#spring的配置
spring:
application:
name: springcloud-consumer-dept #默認註冊進eureka中的實例名稱(顯示大寫)
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/springcloud_db01?useUnicode=true&characterEncoding=utf-8
username: root
password: admin
#eureka的配置,肯定客戶端服務註冊到eureka服務列表內
eureka:
  client:
    register-with-eureka: false  #不向eureka註冊本身
    service-url:  #使用eureka集羣測試
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

 

2.3.啓動類及配置類

在consumer客戶端的配置類上加上@LoadBanlanced,表示當前的請求在客戶端作負載均衡;服務器

@Configuration
public class SpringBeanConfig {
    @Bean
    @LoadBalanced //Ribbon基於客戶端作負載均衡
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

 

@RestController
public class DeptConsumerController {
    @Autowired
    private RestTemplate restTemplate;

    //服務端的請求地址,這裏是本機localhost,也能夠是其餘任意的服務機ip地址
    //private static final String REST_URL_PREFIX = "http://localhost:8001";
    //負載均衡後經過服務名來獲取,由於由客戶端選舉定位到隨機的一個Eureka註冊中心去訪問
    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
}

啓動測試訪問接口:http://localhost:8002/consumer/dept/get/2,訪問成功。restful

 

總結:Ribbon和Eureka整合後consumer能夠直接調用服務而不用關心地址和端口號。

 

3.Ribbon負載均衡配置

Ribbon的負載均衡實現策略主要有:輪詢、隨機、重試三種。下面演示Ribbon的負載均衡,採用建立三個服務提供方的方式,並啓用三個Eureka服務註冊地址。具體思路圖以下:

 

3.1.請求提供者Provider建立

這裏每一個請求者都是一個單體服務,擁有本身獨立的數據庫,訪問接口。可是提供暴露到註冊中心的實例名是惟一的,用於客戶端來作訪問地址的惟一請求,而Ribbon則會經過@LoadBalanced註解對應識別客戶端請求查詢可用的服務列表,調用對應的負載均衡策略。

(1)單個的provider中主要的application.yml配置:

 

server:
  port: 8001
#mybatis的配置
mybatis:
  type-aliases-package: com.fengye.springcloud.pojo
  mapper-locations: classpath:mybatis/mapper/*Mapper.xml
  configuration:
    map-underscore-to-camel-case: true

#spring的配置
spring:
  application:
    name: springcloud-provider-dept  #默認註冊進eureka中的實例名稱(多個服務提供方應該惟一)
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/springcloud_db01?useUnicode=true&characterEncoding=utf-8  #db01/02/03
    username: root
    password: admin

#eureka的配置,肯定客戶端服務註冊到eureka服務列表內
eureka:
 client:
    service-url:
      #集羣配置
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

 

(2)在服務提供方provider的Controller設置請求的調用接口,同時設置負載均衡端口信息:

@RestController
@RequestMapping("/dept")
public class DeptController {
    @Autowired
    private DeptService service;

    //集羣狀況下,用於訂單服務查看到底調用的是哪一個商品微服務節點
    @Value("${server.port}")
    private String port;

    @GetMapping("/queryById/{id}")
    public Dept queryById(@PathVariable("id") Long id){
        Dept dept = service.queryById(id);
        Dept result = new Dept();
        BeanUtils.copyProperties(dept, result);
        result.setDname(result.getDname() + " data from port=" + port);  //查看員工屬於哪一個端口
        System.out.println(result.getDname());
        return result;
    };

}

 

3.2.服務調用方接收並測試

(1)請求調用controller接口編寫:

@RestController
public class DeptConsumerController {
    /**
     * 消費者:不該該有service實現層
     * RestTemplate:提供多種便捷的訪問遠程http服務的方法,提供簡單的restful服務模板(使用簡單無腦粗暴)
     * 參數類型:(url, requestMap, ResponseBean.class)分別表明REST請求地址、請求參數、HTTP響應轉換被轉換成的對象類型
     */
    @Autowired
    private RestTemplate restTemplate;

    //負載均衡後經過服務名來獲取
    private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";


    @RequestMapping("/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id){
        Dept result = restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryById/" + id, Dept.class);
        System.out.println("客戶端請求:data from port= " + result.getDname());
        return  result;
    }
}

 

(2)服務調用方獲取並請求調用請求端口,獲取並打印訪問的端口信息,連續多請求幾回:

 

控制檯打印:

 

 

能夠看到每次訪問請求的端口都在不停變化,客戶端consumer基於Ribbon實現了負載均衡

 

Ribbon文檔相關:

https://github.com/Netflix/ribbon

 

示例代碼已上傳至Github地址:

https://github.com/devyf/SpringCloud_Study/tree/main/springcloud_hello

相關文章
相關標籤/搜索