Hystrix介紹
Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統里,許多依賴不可避免的會呼叫失敗,比如超時、例外等,Hystrix能保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分布式系統的彈性,
“斷路器”本身是一種開關裝置,當某個服務單元發生故障之后,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方回傳一個符合預期的、可處理的備選回應(FallBack),而不長時間的等待或者拋出呼叫方法無法處理的例外,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要地占用,從而避免了故障在分布式系統中的蔓延,乃至雪崩,
github地址:https://github.com/Netflix/Hystrix
服務降級
所謂降級,就是當某個服務出現例外之后,服務器將不再被呼叫,此時服務端可以自己準備一個本地的fallback回呼,回傳一個預設值, 這樣做,雖然服務水平下降,但好歹可用,比直接掛掉要強,當然這也要看適合的業務場景,
可能出現服務降級的情況:
- 程式運行例外
- 服務超時
- 服務熔斷出發服務降級
- 執行緒池/信號量打滿也會導致服務降級
版本說明
Java : 1.8
Spring Boot : 2.1.5.RELEASE
Spring Cloud: Greenwich.SR1
專案說明
eureka-server:eureka服務中心
feign-client :feign生產者
feign-client-intf:feign介面提供者
hystrix-fallback:hystrix降級demo
eureka-server 前面文章已經提供不在粘貼出來了
feign-client-intf:feign介面提供者
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
server介面提供
@FeignClient("feign-client")
public interface IService {
@GetMapping("/sayHi")
public String sayHi();
@PostMapping("/sayHi")
public Friend sayHiPost(@RequestBody Friend friend);
@GetMapping("/retry")
public String retry(@RequestParam(name = "timeout") int timeout);
@GetMapping("/error")
public String error();
}
Friend物體類
@Data
public class Friend {
private String name;
private String port;
}
feign-client :feign生產者
pom.xml
dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.imooc</groupId>
<artifactId>feign-client-intf</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
application.properties
spring.application.name=feign-client
server.port=40006
eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/
Controller
@RestController
public class Controller implements IService {
Logger log = LoggerFactory.getLogger(Controller.class);
@Value("${server.port}")
private String port;
@GetMapping("/sayHi2")
public String sayHi2() {
return "This is " + port;
}
@Override
public String sayHi() {
return "This is " + port;
}
@Override
public Friend sayHiPost(@RequestBody Friend friend) {
log.info("You are " + friend.getName());
friend.setPort(port);
return friend;
}
@Override
public String retry(@RequestParam(name = "timeout") int timeout) {
System.out.println("timeout"+timeout);
while (--timeout >= 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
log.info("retry " + port);
return port;
}
@Override
public String error() {
throw new RuntimeException("black sheep");
}
}
FeignClientApplication啟動類
@EnableDiscoveryClient
@SpringBootApplication
public class FeignClientApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FeignClientApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
}
}
hystrix-fallback:hystrix降級demo

pom.xml
dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.imooc</groupId>
<artifactId>feign-client-intf</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
application.properties
spring.application.name=hystrix-consumer
server.port=50001
spring.main.allow-bean-definition-overriding=true
eureka.client.serviceUrl.defaultZone=http://localhost:20000/eureka/
# 開啟Feign下面的Hystrix功能
feign.hystrix.enabled=true
# 是否開啟服務降級
hystrix.command.default.fallback.enabled=true
# 全域超時
hystrix.command.default.execution.timeout.enabled=true
# 超時時間
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000
# 超時以后終止執行緒
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true
# 取消的時候終止執行緒
hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=true
# hystrix.command.MyService#retry(int).execution.isolation.thread.timeoutInMilliseconds=3000
# 每臺機器最大重試次數
feign-client.ribbon.MaxAutoRetries=0
# 可以再重試幾臺機器
feign-client.ribbon.MaxAutoRetriesNextServer=0
# 連接超時
feign-client.ribbon.ConnectTimeout=1000
# 業務處理超時
feign-client.ribbon.ReadTimeout=8000
# 在所有HTTP Method進行重試
feign-client.ribbon.OkToRetryOnAllOperations=false
Controller
@RestController
public class Controller {
@Autowired
private MyService myService;
@Autowired
private RequestCacheService requestCacheService;
@GetMapping("/fallback")
public String fallback() {
return myService.error();
}
@GetMapping("/timeout")
public String timeout(Integer timeout) {
System.out.println(timeout);
return myService.retry(timeout);
}
@GetMapping("/timeout2")
@HystrixCommand(
fallbackMethod = "timeoutFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value="3000")
}
)
public String timeout2(Integer timeout) {
return myService.retry(timeout);
}
public String timeoutFallback(Integer timeout) {
return "success";
}
@GetMapping("/cache")
public Friend cache(String name) {
@Cleanup HystrixRequestContext context =
HystrixRequestContext.initializeContext();
Friend friend = requestCacheService.requestCache(name);
friend = requestCacheService.requestCache(name);
return friend;
}
}
MyService
@FeignClient(name = "feign-client", fallback = Fallback.class)
public interface MyService extends IService {
}
Fallback 降級處理類
@Slf4j
@Component
public class Fallback implements MyService {
@Override
//@HystrixCommand(fallbackMethod = "fallback2")
public String error() {
log.info("Fallback: I'm not a black sheep any more");
throw new RuntimeException("first fallback");
}
@HystrixCommand(fallbackMethod = "fallback3")
public String fallback2() {
log.info("fallback again");
throw new RuntimeException("fallback again");
}
public String fallback3() {
log.info("fallback again and again");
return "success";
}
@Override
public String sayHi() {
return null;
}
@Override
public Friend sayHiPost(@RequestBody Friend friend) {
return null;
}
@Override
public String retry(@RequestParam(name = "timeout") int timeout) {
return "You are late !";
}
}
RequestCacheService Request Cache減壓
@Slf4j
@Service
public class RequestCacheService {
@Autowired
private MyService service;
@CacheResult
@HystrixCommand(commandKey = "cacheKey")
public Friend requestCache(@CacheKey String name) {
log.info("request cache " + name);
Friend friend = new Friend();
friend.setName(name);
friend = service.sayHiPost(friend);
log.info("after requesting cache " + name);
return friend;
}
}
HystrixFallbackApplication啟動類
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class HystrixFallbackApplication {
public static void main(String[] args) throws NoSuchMethodException {
new SpringApplicationBuilder(HystrixFallbackApplication.class)
.web(WebApplicationType.SERVLET)
.run(args);
// System.out.println(Feign.configKey(MyService.class,
// MyService.class.getMethod("retry", int.class)));
}
}
測驗
依次啟動:
eureka-server:eureka服務中心
feign-client :feign生產者
hystrix-fallback:hystrix降級demo

Fallback多級降級測驗
測驗步驟:
1.通過postman來呼叫hystrix-fallback fallback介面

2.然后通過feign來呼叫feign-client的error介面來獲取一個例外看看能不能降級,
3.多級降級處理

postman 放回的結果,然后分析一下結果,

在feign-client當中 拋出了一個RuntimeException的錯誤,然后會被hystrix進行降級處理,

我們再去hystrix-fallback的控制臺看看有沒有被降級,

這三條輸出對應的就是之前多級處理的列印的結果說明 多級降級是成功的,
Timeout降級測驗
1.設定全域的超時時間 超過時間就會Timeout降級 這里我是設定的3s

2通過postman來呼叫hystrix-fallback timeout介面

3.然后通過feign來呼叫feign-client的retry介面讓執行緒sleep相應的時間

4.如果沒有超時就會retrun 出feign-clien埠號 超時了的話就會進入timeout降級處理類

5.先測驗2s 沒有超時的結果

6.先然后測驗3s 超時的結果

Request Cache減壓測驗
1.通過postman來呼叫hystrix-fallback cache介面,然后介面里面連續呼叫了 兩次requestCacheService.requestCache(name);
如果列印兩遍相同的log說明沒有被快取到本地,解壓失敗,
如果只列印一遍og說明有被快取到本地,解壓成功,

requestCacheService.requestCache

呼叫介面

只列印了一遍Log說明解壓成功

以上有問題請指出來!交流學習
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/225335.html
標籤:java
上一篇:如果在try里面執行return,那么還會不會執行finally?
下一篇:大廠面試必備——Java集合框架
