目錄
本文環境:Java jdk 8 + Spring boot 2.1.3 + spring cloud Greenwich.SR1 + spring 5.1.5。
netflix ribbon 負載均衡
1、ribbon 與 eureka 一樣都是 netflix 下的子項目,spring cloud 對它們進行了集成。
2、ribbon 是一個基於 HTTP 和 TCP 的客戶端負載均衡工具,可以輕鬆地將面向服務的 REST 模版請求自動轉換成客戶端負載均衡的服務調用。
3、Spring Cloud Ribbon 雖然只是一個工具類框架,它不像服務註冊中心、配置中心、API網關那樣需要獨立部署,但是它幾乎存在於每一個Spring Cloud構建的微服務和基礎設施中。因爲微服務間的調用,API 網關的請求轉發等內容,實際上都是通過 Ribbon 實現。
4、nginx 在服務端實現負載均衡,ribbon 在客戶端提供負載均衡。即客戶端程序使用 ribbon 後,就會自動對多個節點微服務進行負載均衡。
5、負載均衡有好幾種實現策略,常見的有:隨機 (Random)、輪詢 (RoundRobin)、一致性哈希(ConsistentHash)、哈希 (Hash)、加權(Weighted)。默認是輪詢。官網地址:
https://github.com/Netflix/ribbon
6、使用下面的命令啓動多個微服務節點,動態修改應用端口以及實例名稱。
java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9396 --eureka.instance.instance-id=changSha-food-9396
java -jar eurekaclient_food-0.0.1-SNAPSHOT.jar --server.port=9397 --eureka.instance.instance-id=changSha-food-9397
如上所示此時 Eureka 服務端可以看到微服務 EUREKA-CLIENTFOOD 下面有3個節點。
netflix Ribbon 基本使用
1、Ribbon 是客戶端實現的負載均衡,也就是誰發起請求,誰自己實現負載均衡,所以 eurekaclient_cat 向 eurekaclient_food 發起請求,則應該修改 eurekaclient_cat 應用。第一步應該引入 Ribbon 組件,但是 eureka 組件默認已經依賴了 ribbon 組件,所以只要引入了 eureka 就已經引入了 ribbon。
......
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
......
2、修改 eurekaclient_cat 創建 RestTemplate 實例的代碼,加上 @LoadBalanced 使 RestTemplate 具有負載均衡的能力。
/**
* @SpringBootApplication 註解自己依賴了 @Configuration 註解,所以可以直接在啓動類上使用 @Bean 註解
* 當然也可以新建一個配置類(@Configuration) 專門管理需要創建的實例
* @Bean 作用就是使用 DI 往 spring 容器中傳教實例,以後可以直接使用 @Resource 取值使用。
* <p>
* LoadBalanced:英文就是負載均衡的意思,@LoadBalanced 註解表示 RestTemplate 具有負載均衡的能力。
* 意味着 RestTemplate 每次發送 http 請求時,都會根據 ribbon 的負載均衡機制向微服務下的某臺節點服務器發送請求
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
//RestTemplate 有3個構造器,這裏使用無參構造器,底層使用 jdk 原生的 java.net 下 api 進行 http 操作
return new RestTemplate();
}
3、然後修改 RestTemplate 發起 http 請求的代碼,將原來寫死的 ip與端口換成微服務的名稱,本文是爲了演示簡單,微服務名稱直接寫死了,實際開發中可以從配置文件中獲取:
@Resource
private RestTemplate restTemplate;
//通過 id 獲取貓咪信息。這裏只是簡單的模擬,並不是操作數據庫
//請求地址:http://localhost:9394/getCatById?id=110
@GetMapping("getCatById")
public String getCatById(String id) throws IOException {
//貓咪的基本信息,這裏直接設置
JsonNodeFactory nodeFactory = JsonNodeFactory.instance;
ObjectNode objectNode = nodeFactory.objectNode();
objectNode.put("id", id);
objectNode.put("color", "white");
objectNode.put("age", 0.2);
//貓咪的食譜/菜譜信息調用 eurekaclient_food 微服務進行獲取。
//未使用負載均衡時的地址:http://localhost:9395/getHunanCuisine。使用負載均衡後,其中的 ip:port 必須使用微服務名稱代替
//EUREKA-CLIENT-FOOD 是在註冊中心註冊好的微服務名稱(不是節點名稱),也就是微服務配置文件中使用 spring.application.name 配置的名稱
String foodMenu = restTemplate.getForObject("http://EUREKA-CLIENT-FOOD/getHunanCuisine", String.class);
if (!StringUtils.isEmpty(foodMenu)) {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(foodMenu);//先將 json 字符串專戶 json 節點對象
objectNode.putPOJO("menu", jsonNode);//對象節點插入子節點
}
return objectNode.toString();
}
5、代碼很簡單,修改兩處就好了,接下來訪問測試:
可以看出 ribbon 默認採用的輪詢的策略,即對集羣的服務輪流進行訪問。
注意:具有負載均衡後的 RestTemplate 請求時只能使用微服務名稱,無法再直接使用 ip:port 的形式,如果應用中還需要直接使用 ip 請求,則可以再提供一個非負載均衡的 RestTemplate 實例即可,使用時根據方法名注入。
@Bean
RestTemplate restTemplateNotBalance() {
return new RestTemplate();
}
帶負載均衡(@LoadBalanced)的 RestTemplate 必須使用微服務名稱發起請求,不能使用 ip:port
不帶負載均衡(@LoadBalanced)的 RestTemplate 不能使用微服務名稱發起請求,只能使用 ip:port
更多負載均衡策略可以參考《Ribbon 負載均衡策略 與 脫離 Eureka 使用、LoadBalancerClient》
演示源碼 github 地址:https://github.com/wangmaoxiong/ribbon_study
Ribbon 超時時間配置
官網:/spring-cloud-netflix/2.1.0.RELEASE/single/spring-cloud-netflix.html#_zuul_timeouts
ribbon:
ConnectTimeout: 3000 #連接超時時間
ReadTimeout: 60000 #讀取超時時間
SocketTimeout: 60000 #socket 超時時間