前言:
Spring Cloud系列教程的所有博客均在下方的目錄鏈接中,方便大家查找和閱讀。建議按照順序學習,對於項目搭建有疑問的可以着重看目錄裏的第二篇博客。
Spring cloud學習專欄目錄
一、Ribbon簡介
Ribbon是Netflix發佈的雲中間層服務開源項目,其主要功能是提供客戶端側負載均衡算法。Ribbon客戶端組件提供一系列完善的配置項如連接超時,重試等。簡單的說,Ribbon是一個客戶端負載均衡器,我們可以在配置文件中列出Load Balancer後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連接等)去連接這些機器,我們也很容易使用Ribbon實現自定義的負載均衡算法。
下圖展示了Eureka使用Ribbon時候的大致架構:
Ribbon工作時分爲兩步:第一步先選擇 Eureka Server, 它優先選擇在同一個Zone且負載較少的Server;第二步再根據用戶指定的策略,在從Server取到的服務註冊列表中選擇一個地址。其中Ribbon提供了多種策略,例如輪詢round robin、隨機Random、根據響應時間加權等。
二、利用Ribbon解決車票微服務中的硬編碼問題
問題回顧
之前我們在TicketService中的 url是寫死的,而我們現在已經會使用Eureka了,在配合上ribbon就可以去eureka中查詢服務地址了。
2.1 修改車票微服務啓動類,添加負載均衡的註解
打開車票微服務的pom文件,可以看到eureka的依賴中整合了ribbon,所以我們就不需要單獨去添加ribbon的依賴。
———————————————————————————————————
在RestTemplate上添加@LoadBalance註解,這樣restTemplate就具備了負載均衡的能力。
@SpringBootApplication
@EnableEurekaClient
public class TicketServiceApplication {
public static void main(String[] args) {
SpringApplication.run(TicketServiceApplication.class, args);
}
/*
* 向Spring容器中添加RestTemplate對象
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.2 修改service中的方法實現
2.2.1 將地址和端口用我們之前在用戶微服務的application.properties中設置的服務名稱替換
@Service
public class TicketService {
@Autowired
private RestTemplate restTemplate;
/*
* 查詢車票信息時查詢用戶的信息(這裏爲了簡化操作就不對車票信息進行查詢,直接去調用查詢用戶信息的接口)
*/
public User queryTicketInfo(Long id) {
//向用戶微服務中的接口發送請求的地址
//String url = "http://localhost:8081/getUserInfo/"+ id;
String url = "http://microservice-provide-user/getUserInfo/"+ id;
return restTemplate.getForObject(url, User.class);
}
}
2.2.2 啓動服務進行測試
將eureka服務,用戶微服務以及車票微服務進行啓動。
訪問車票微服務中的接口地址 http://localhost:8082/getTicketInfo/1,可以看到成功查詢出了用戶信息,說明硬編碼問題得到了解決
三、測試負載均衡
通過剛纔的測試我們可以知道,硬編碼問題已經得到了解決,車票微服務成功請求到了用戶微服務。但要測試負載均衡我們就需要啓動多個服務提供者也就是用戶微服務來進行測試。
3.1 啓動兩個用戶微服務
3.1.1 修改車票微服務中的service方法
按下圖添加代碼,打印出端口信息主要是爲了方便我們查看負載均衡的情況。
@Service
public class TicketService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
/*
* 查詢車票信息時查詢用戶的信息(這裏爲了簡化操作就不對車票信息進行查詢,直接去調用查詢用戶信息的接口)
*/
public User queryTicketInfo(Long id) {
String serviceId = "microservice-provide-user";
ServiceInstance serviceInstance = loadBalancerClient.choose(serviceId);
//打印出請求了哪個端口的用戶微服務
System.out.println("請求了" + serviceInstance.getPort());
//向用戶微服務中的接口發送請求的地址
//String url = "http://localhost:8081/getUserInfo/"+ id;
String url = "http://microservice-provide-user/getUserInfo/"+ id;
return restTemplate.getForObject(url, User.class);
}
}
3.1.2 啓動微服務
將eureka服務,用戶微服務以及車票微服務進行啓動。第一個用戶微服務啓動好之後,對用戶微服務的配置文件中的端口號進行修改。
# 配置api端口號
#server.port=8081
server.port=8090
# tomcat
server.tomcat.uri-encoding=UTF-8
# 服務名稱,也就是在eureka
spring.application.name=microservice-provide-user
# 是否啓動註冊,這是一個客戶端需要註冊
eureka.client.register-with-eureka=true
# 是否檢索服務
eureka.client.fetch-registry=true
# 服務註冊中心的地址
eureka.client.service-url.default-zone=http://localhost:8761/eureka
改好之後我們再次啓動用戶微服務,啓動好之後我們去eureka中查看。可以看到兩個用戶微服務以及啓動好了,一個是8090端口一個是8081端口。
3.2 開始測試負載均衡
訪問車票微服務的接口: http://localhost:8082/getTicketInfo/1
這裏正常的情況應該是一個接口請求一次,但我這裏總是隻請求一個接口,不是默認的輪詢規則。我之後通過自定義配置的方式發現隨機規則是正常的但是輪詢依舊不正常,所以這裏我們先忽略這個問題,繼續講解自定義配置ribbon。
四、通過代碼自定義ribbon的負載均衡規則
4.1 新建一個配置類TestConfiguration
注意這個類的放置的位置是有規則的,他不能放在@ComponentScan或者是@SpringBootApplication掃描的包裏。這裏的話@SpringBootApplication也就是我們啓動類上的註解,他掃描的的是啓動類所在的包已經它的子包。所以這裏我們專門在啓動類的外面建了一個包去放配置文件。
如果你一定要和啓動類放在同級目錄的話,就要通過一些註解和配置把該類,從掃描的列表中除去,我覺得相對來說有點麻煩這裏就不做講解。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
@Configuration
public class TestConfiguration {
@Autowired
private IClientConfig config;
@Bean
public IRule ribbonRule(IClientConfig config) {
//自定義爲隨機規則,你也可以根據需要選擇其他規則。只需要將RandomRule改成其他的規則即可
return new RandomRule();
}
}
4.2 在服務消費者車票微服務的啓動類上添加註解
name就是用戶微服務application.proerties中配置的spring.application.name
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import com.spring.config.TestConfiguration;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "microservice-provide-user",configuration = TestConfiguration.class)
public class TicketServiceApplication {
public static void main(String[] args) {
SpringApplication.run(TicketServiceApplication.class, args);
}
/*
* 向Spring容器中添加RestTemplate對象
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
4.3 重啓車票微服務進行測試
訪問車票微服務的接口: http://localhost:8082/getTicketInfo/1
可以看到8081和8090兩個接口被隨機訪問,說明配置生效了
五、Ribbon 自帶的負載均衡策略
這裏簡單列舉幾個:
BestAvailableRule 先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然後選擇一個併發量最小的服務
RandomRule: 隨機選擇
RoundRobinRule: 輪詢一個server一次
RetryRule: 先輪詢,如果獲取失敗則在指定時間內重試,重新輪詢可用的服務。
WeightedResponseTimeRule: 根據平均響應時間計算所有服務的權重,響應越快的服務權重越高,越容易被選中。一開始啓動時,統計信息不足的情況下,使用輪詢。
ZoneAvoidanceRule: 複合判斷 server 所在區域的性能和 server 的可用性選擇服務器