Hystrix叢集及叢集監控turbine
技術標籤:ribbonspring cloud
目錄
Hystrix叢集及監控turbine
前面Dashboard演示的僅僅是單機服務監控,實際專案基本都是叢集,所以這裡叢集監控用的是turbine。
turbine是基於Dashboard的。
先搞個叢集;
再microservice-student-provider-hystrix-1004專案的基礎上再搞一個microservice-student-provider-hystrix-1005
程式碼和配置都複製一份,然後修改幾個地方
--- server: port: 1004 context-path: / spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 username: xiaoyang password: 123 jpa: hibernate: ddl-auto: update show-sql: true application: name: microservice-student profiles: provider-hystrix-1004 eureka: instance: hostname: localhost appname: microservice-student instance-id: microservice-student:1004 prefer-ip-address: true client: service-url: defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/ info: groupId: com.xiaoyang.testSpringcloud artifactId: microservice-student-provider-hystrix-1004 version: 1.0-SNAPSHOT userName: http://xiaoyang.com phone: 123456 --- server: port: 1005 context-path: / spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 username: xiaoyang password: 123 jpa: hibernate: ddl-auto: update show-sql: true application: name: microservice-student profiles: provider-hystrix-1005 eureka: instance: hostname: localhost appname: microservice-student instance-id: microservice-student:1005 prefer-ip-address: true client: service-url: defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/ info: groupId: com.xiaoyang.testSpringcloud artifactId: microservice-student-provider-hystrix-1005 version: 1.0-SNAPSHOT userName: http://xiaoyang.com phone: 123456 --- server: port: 1006 context-path: / spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 username: xiaoyang password: 123 jpa: hibernate: ddl-auto: update show-sql: true application: name: microservice-student profiles: provider-hystrix-1006 eureka: instance: hostname: localhost appname: microservice-student instance-id: microservice-student:1006 prefer-ip-address: true client: service-url: defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/ info: groupId: com.xiaoyang.testSpringcloud artifactId: microservice-student-provider-hystrix-1006 version: 1.0-SNAPSHOT userName: http://xiaoyang.com phone: 123456
啟動類配置
@EnableCircuitBreaker
@EntityScan("com.xiaoyang.*.*")
@EnableEurekaClient
@SpringBootApplication
這樣的話 就有了 hystrix叢集服務
我們新建專案microservice-student-consumer-hystrix-turbine-91
pom.xml加下依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId> spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-turbine</artifactId>
</dependency>
application.yml
server:
port: 91
context-path: /
eureka:
client:
service-url:
defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/
turbine:
app-config: microservice-student # \u6307\u5B9A\u8981\u76D1\u63A7\u7684\u5E94\u7528\u540D\u79F0
clusterNameExpression: "'default'" #\u8868\u793A\u96C6\u7FA4\u7684\u540D\u5B57\u4E3Adefault
spring:
application:
name: turbine
Feign、Hystrix整合
前面的程式碼,用@HystrixCommand fallbackMethod是很不好的,因為和業務程式碼耦合度太高,不利於維護,所以需要解耦,這我們講下Feign Hystrix整合
comm專案
package com.xiaoyang.microservicecommon.service;
import com.xiaoyang.microservicecommon.entity.Student;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
import java.util.Map;
/**
* Student Feign介面客戶端
*
* @author xiaoyang
*/
@FeignClient(value = "MICROSERVICE-STUDENT",fallbackFactory=StudentClientFallbackFactory.class)
public interface StudentClientService {
/**
* 根據id查詢學生資訊
*
* @param id
* @return
*/
@GetMapping(value = "/student/get/{id}")
public Student get(@PathVariable("id") Integer id);
/**
* 查詢學生資訊
*
* @return
*/
@GetMapping(value = "/student/list")
public List<Student> list();
/**
* 新增或者修改學生資訊
*
* @param student
* @return
*/
@PostMapping(value = "/student/save")
public boolean save(Student student);
/**
* 根據id刪除學生資訊
*
* @return
*/
@GetMapping(value = "/student/delete/{id}")
public boolean delete(@PathVariable("id") Integer id);
@RequestMapping("/student/ribbon")
public String ribbon();
@RequestMapping("/student/hystrix")
public Map<String, Object> hystrix();
}
StudentClientFallbackFactory
package com.xiaoyang.microservicecommon.service;
import com.xiaoyang.microservicecommon.entity.Student;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author xiaoyang
* @create 2020-12-14 19:24
*/
@Component
public class StudentClientFallbackFactory implements FallbackFactory<StudentClientService> {
@Override
public StudentClientService create(Throwable cause) {
return new StudentClientService() {
@Override
public boolean save(Student student) {
return false;
}
@Override
public List<Student> list() {
return null;
}
@Override
public Map<String, Object> hystrix() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("code", 500);
map.put("info", "系統繁忙,稍後重試");
return map;
}
@Override
public Student get(Integer id) {
return null;
}
@Override
public boolean delete(Integer id) {
return false;
}
@Override
public String ribbon() {
return null;
}
};
}
}
ribbon和hystrix超時時間設定
先看消費端配置
server:
port: 80
context-path: /
eureka:
client:
service-url:
defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/
register-with-eureka: false
feign:
hystrix:
enabled: true
ribbon:
ReadTimeout: 550 #請求處理的超時時間
ConnectTimeout: 550 #請求連線的超時時間
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 600
服務端:hystrix04
@ResponseBody
@GetMapping(value="/hystrix")
public Map<String,Object> hystrix() throws InterruptedException{
Thread.sleep(500);
return studentService.hystrix();
}
服務端:hystrix05、hystrix06
/**
* 測試Hystrix服務降級
* @return
* @throws InterruptedException
*/
@ResponseBody
@GetMapping(value="/hystrix")
public Map<String,Object> hystrix() throws InterruptedException{
Thread.sleep(100);
return studentService.hystrix();
}
這裡可以看到ribbon
的超時時間設定短於hystrix
,但是這裡訪問的時候,controller
層分別sleep
了0.1s和0.5s,ribbon
的超時設定為0.55s。那麼,訪問的時候,是可以正常訪問的,並不會ribbon
超時或者熔斷。
問題來了:
眾所周知,ribbon是有重試機制的,而且是4次
如果這時候我斷掉hystrix04服務,ribbon的輪詢機制在輪詢訪問hystrix04時,由於它已經斷掉,它的訪問超時時間是0.5s,而hystrix的超時降級熔斷時間為0.6s,此時雖然ribbon超時(或其他原因),但是是第一次訪問,且超時時間小於熔斷超時時間,所以不會觸發熔斷,輪詢機制會切換到其他節點去
但是重新整理一次瀏覽器,第二次輪詢到hystrix04服務提供者時,就會觸發熔斷,因為加上第一次的訪問時間,已經超過了hystrix的熔斷超時設定,那麼這個時候ribbon重試失敗 ,觸發熔斷(非完全熔斷,具體可看上篇博文)
所以,如果不考慮ribbon的重試機制,ribbon和hystrix的超時設定並不一定非要誰大誰小,但是重試機制個人覺得是非常重要的,如果沒有重試機制,節點超時或者因為其他原因斷掉後就不用這個節點,不太現實(一個節點相當於一個伺服器)
而要考慮ribbon的重試機制,建議將hystrix降級熔斷的超時時間設定比ribbon超時時間長,不然重試機制的意義在哪,一重試你就熔斷了,hystrix超時時間設定長點,即使重試時此節點連線不上他也會負債均衡分發到另一個節點,不會進行錯誤資訊展示
具體可以自行測試
over…