What is Hystrix
Hystrix is an open source library for dealing with delay and fault tolerance of distributed systems. In distributed systems, many dependencies inevitably fail to call, such as timeout and exception. Hystrix can ensure that in the case of a dependency failure, it will not lead to overall service failure, avoid cascading failures, and improve the elasticity of distributed systems.
"Circuit breaker" itself is a kind of switching device. When a service unit fails, it returns an expected and treatable alternative response (FallBack) to the caller through the fault monitoring of the circuit breaker (similar to a blown fuse), rather than waiting for a long time or throwing an exception that the caller cannot handle, This ensures that the thread of the service caller will not be occupied unnecessarily for a long time, so as to avoid the spread and even avalanche of faults in the distributed system.
Use of Hystrix
- pom introduces dependency
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
- The startup class is annotated with @ EnableHystrix or @ enablercircuitbreaker
@SpringBootApplication @EnableDiscoveryClient @EnableHystrix @EnableFeignClients public class EurekaConsumerApp { public static void main(String[] args) { new SpringApplicationBuilder(EurekaConsumerApp.class) .web(WebApplicationType.SERVLET).run(args); } }
Service degradation and timeout
Degradation: a microservice takes too long to respond or is unavailable. It cannot return the error message or keep it stuck. Therefore, it is necessary to prepare a corresponding strategy. When this happens, call this strategy directly and return the request quickly.
- Add @ HystrixCommand annotation on the method and specify fallbackMethod degradation policy
- Provider simulation exception
@RestController @RequestMapping("client") public class IndexController { @Autowired RestTemplate restTemplate; @GetMapping @HystrixCommand(fallbackMethod = "selectFallback") public String select(String type){ HashMap<String, String> map = new HashMap<>(); map.put("type",type); return restTemplate.getForObject("http://EUREKA-PRODUCT/product?type={type}", String.class,map); } public String selectFallback(String type) { return "service degradation :" + type; } }
@RestController @RequestMapping("product") public class UserController { private static String shareName = "init name"; @Value("${server.port}") private String serverPort; @GetMapping public String select(String type) throws InterruptedException { if ("abnormal".equals(type)){ throw new RuntimeException("Simulation anomaly"); } if ("overtime".equals(type)){ System.out.println("Timeout tests "); Thread.sleep(3000); } return serverPort + ":" + shareName; } }
Timeout: Hystrix has a default timeout monitoring mechanism. When the request exceeds 1s, it will timeout, and timeout will also trigger degradation. Here, you can configure the timeout duration by configuring the class.
hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 1000 # Time out for degradation
Usage scenario: when the system cannot carry such a large amount of concurrency in the double 11 second kill or promotion activities, you can consider closing some unimportant microservices first (returning a more friendly information in the degradation method) and giving resources to the main microservices.
Fusing and current limiting
Fusing: fusing is like a fuse. When your circuit fails, hystrix will adopt a fusing mechanism to prohibit you from calling services. After disconnection, it will still be called occasionally to judge whether the service is restored
hystrix: command: default: circuitBreaker: requestVolumeThreshold: 10 # default 20 this attribute sets the minimum number of requests that will trigger the circuit in the scrolling window metrics: rollingStats: timeInMilliseconds: 10000 # When used in conjunction with requestvolumthreshold, 10 errors within 10s will open the circuit breaker
Current limit: limit the use of micro services. For example, limit the number of threads.
@GetMapping @HystrixCommand(fallbackMethod = "selectFallback" , threadPoolKey = "order", threadPoolProperties ={@HystrixProperty(name = "coreSize",value = "2") ,@HystrixProperty(name = "maxQueueSize",value = "1")}) public String select(String type){ HashMap<String, String> map = new HashMap<>(); map.put("type",type); return restTemplate.getForObject("http://EUREKA-PRODUCT/product?type={type}",String.class,map); }
threadPoolKey is the unique ID of the thread pool. hystrix will count your ID to see if the thread occupation exceeds. If it exceeds, it will directly degrade the call
For example, if the value given by coreSize here is 2, assuming that the method call time is 3s, if more than 2 requests come in within 3s, all the remaining requests will be degraded
What is the difference between fusing and degradation?
Feign integrates Hystrix
-
application.yml configuration, open
feign: hystrix: enabled: true
-
Feign interface modification
@FeignClient(name = "EUREKA-PRODUCT",fallbackFactory = UserClientFallBack.class,path = "/product") public interface UserClient { @GetMapping public String select(@RequestParam("type") String type); }
@Component public class UserClientFallBack implements UserClient{ @Override public String select(String type) { return "Service degradation: Feign hystrix"; } }
-
If you get the specific error information, modify it as follows
@Component public class UserClientFallBackFactory implements FallbackFactory<UserClient> { @Override public UserClient create(Throwable throwable) { return new UserClient() { @Override public String select(String type) { String message = throwable.getMessage(); System.err.println(message); return "Service degradation: Feign hystrix"+message; } }; } } @FeignClient(name = "EUREKA-PRODUCT",fallbackFactory = UserClientFallBackFactory.class,path = "/product") public interface UserClient { @GetMapping public String select(@RequestParam("type") String type); }