四、SpringCloud之Ribbon負載均衡
Ribbon是一個客戶端的負載均衡(Load Balance)工具,可以很好的控制HTTP和TCP的一些行為,通過基於多種負載均衡演算法達到系統的高可用(HA)
官方資料:
以下內容是基於上一節的工程,使用Ribbon+RestTemplate 實現服務間通訊。
1、在microservice-dept-consumer-80
服務消費者中pom.xml增加Ribbon依賴
<!-- Eureka client -->
<dependency>
<groupId>org.springframework.cloud</groupId >
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId >
</dependency>
<!-- springcloud config -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2、配置對應的application.yml配置
server:
context-path: /
port: 80
eureka:
client:
register-with-eureka: false #false表示不向註冊中心註冊自己,因為本身應用就是註冊中心
service-url:
#叢集配置
defaultZone: http://eureka-server-5001.com:5001/eureka/, http://eureka-server-5002.com:5002/eureka/,http://eureka-server-5003.com:5003/eureka/
3、使用@LoadBalanced
開啟客戶端負載均衡
@Configuration
public class RestTemplateConfig {
/**
* 呼叫restful服務模版,客戶端模版工具
* @return
*/
@LoadBalanced //開始客戶端負載均衡
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
4、修改controller類DeptConsumerController
URL對應的主機名為微服務例項名,Euraka整合Ribbon配置OK後就可以使用服務例項名訪問,不需要提供IP和埠
@RequestMapping("/consumer")
@RestController
public class DeptConsumerController {
// private final static String URL_PREFIX = "http://localhost:8001";
//Euraka整合Ribbon配置OK後就可以使用服務例項名訪問,不需要提供IP和埠
private final static String URL_PREFIX = "http://MICROSERVICE-DEPT";
5、負載均衡配置
為了模擬多個服務例項,複製3個服務提供者microservice-dept-provider-8001
,microservice-dept-provider-8002
,
microservice-dept-provider-8003
修改埠分別為8001,8002,8003
在controller中增加port輸出,用於辨別負載均衡是否生效。
@Value("${server.port}")
private Integer port;
@GetMapping("/depts")
public List<Dept> depts() {
//新增埠資訊
List<Dept> list = deptService.selectList();
return list.stream().map(dept->{
dept.setPort(port);
return dept;
}).collect(Collectors.toList());
}
6、分別啟動Eureka sever、服務提供者
會在Eureka註冊中心中分別註冊8001,8002,8003,3個服務例項
啟動80埠消費應用microservice-dept-consumer-80
由於restTemplate 啟用了ribbon 負載均衡,而Ribbon預設使用輪詢演算法,因此會輪流呼叫8001、8002、8003服務
7、自定義Ribbon的負載均衡策略
Ribbon提供了很多負載均衡策略的實現用於獲取服務,預設使用輪詢的策略,我們可以通過修改配置指定使用哪個策略,也可以自定義我們自己的策略。
在RestTemplateConfig.java
配置類中增加我們需要的指定的負載均衡策略
/**
* 修改我們需要的負載均衡策略
* @return
*/
@Bean
public IRule myRule(){
return new RandomRule(); //修改預設的演算法為隨機演算法
}
只針對某個服務例項客製化指定Ribbo負載均衡策略
使用@RibbonClient
註解應用到主啟動類上,指定對應的配置類。
自定義的配置類不能在@ComponentScan
的掃描範圍內,否則 會別所有的ribbon客戶端共享,就達不到客製化目地。
(1)在主啟動類外的包org.pu.rule下建立我們自己指定策略的配置類MyRuleConfig.java
。
@Configuration
public class MyRuleConfig {
/**
* 修改我們需要的負載均衡策略
* @return
*/
@Bean
public IRule myRule(){
return new RandomRule(); //修改預設的演算法為隨機演算法
}
}
(2)在主啟動類DeptConsumerApplication.java
上增加@RibbonClient
註解
//啟動該微服務的時候會載入客製化策略的配置類,使其生效
@RibbonClient(name="MICROSERVICE-DEPT",configuration=MyRuleConfig.class)
@SpringBootApplication
public class DeptConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerApplication.class, args);
}
}
自定義負載均衡策略:
可以模仿下面隨機策略(RandomRule.java
)來實現我們自己的策略:
//隨機演算法
@SuppressWarnings({"RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE"})
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
return null;
}
Server server = null;
while (server == null) {
if (Thread.interrupted()) {
return null;
}
List upList = lb.getReachableServers(); //獲取線上的服務
List allList = lb.getAllServers(); //獲取所有的服務
int serverCount = allList.size();
if (serverCount == 0) {
return null;
}
int index = this.rand.nextInt(serverCount); //隨機獲取
server = (Server) upList.get(index);
if (server == null) {
Thread.yield();
}
if (server.isAlive()) {
return server;
}
server = null;
Thread.yield();
}
return server;
}