[TOC]
1. Get to know Hystrix
Hystrix is a delay and fault-tolerant library, which aims to isolate remote systems, services and third-party libraries, organize cascading failures, and realize recovery capability in distributed systems with load.
In the case of multiple systems and microservices, a mechanism is needed to deal with delays and failures, and to protect the integrated system in a stable state. Hystrix is a component of this capability.
- Delay and failure are protected and controlled by client library.
- Stop cascading faults in a complex distributed system
- Fast failure, fast recovery
- Back off and graceful degradation under reasonable circumstances
- Enable near real-time monitoring, warning and operation control
1.2 working mechanism of fuse:
- After application mode in distributed system, the service caller can judge whether some services are slow or there is a large number of timeouts, and can take the initiative to fuse and prevent the whole system from being dragged down.
- Moreover, Hystrix can realize elastic fault tolerance and automatically reconnect when the situation improves.
1. Under normal operation, the client requests to call the service API interface
2. When there is an exception in a service, it will directly roll back the failure and degrade the service
3. When the service is busy, if there is an exception in the service, a friendly prompt will be returned instead of a direct error. Although the user's access is denied, a result will be returned
When the system is very busy, some secondary services are temporarily interrupted, priority is given to ensuring the smooth flow of main services, and all resources are given priority to the use of main services. For example, during the double 11 and 618, JD tmall will adopt such a strategy
Function: in case of service error, fuse the service, protect the caller and prevent the avalanche.
When using feign fuse, feign does not turn on the Hystrix fuse by default and needs to be configured manually.
1.3. Example
pom
<!--Fuse--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
I. @ EnableHystrix: turn on the Hystrix fuse
package com.czxy; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.netflix.hystrix.EnableHystrix; /** * Created by Clouds fall in front of the court */ @SpringBootApplication @EnableEurekaClient @EnableHystrix //Open fuse public class Client4Application { public static void main(String[] args) { SpringApplication.run(Client4Application.class,args); } }
II. dao, remote call to add fuse alternative, add annotation + alternative method
@HystrixComman: fallbackMethod specifies which method is called for graceful degradation return when the method marked by the annotation fails or makes an error, shielding the user from the error and giving an elegant prompt.
package com.czxy.dao; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; /** * Created by Clouds fall in front of the court */ @Component public class DataDao { @Resource private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "dataFallback") public ResponseEntity<String> data(){ String url = "http://service4/test"; return restTemplate.getForEntity(url,String.class); } /** * Handling method of fuse timeout * @return */ public ResponseEntity<String> dataFallback(){ return ResponseEntity.ok("Temporary data"); } }
3. Change the service provider method, add thread sleep, 0 ~ ~ 2000 random (easy to test)
package com.czxy.controller; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.Random; /** * Created by Clouds fall in front of the court */ @RestController @RequestMapping("/test") public class TestController { @GetMapping public ResponseEntity<String> test(HttpServletRequest request) throws Exception { //Analog delay Thread.sleep(new Random().nextInt(2000)); return ResponseEntity.ok("test data" + request.getServerPort()); } }
IV. optimize dao and print time
package com.czxy.dao; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; /** * Created by Clouds fall in front of the court */ @Component public class DataDao { @Resource private RestTemplate restTemplate; @HystrixCommand(fallbackMethod = "dataFallback") public ResponseEntity<String> data(){ //1 record start time long start = System.currentTimeMillis(); //2 call String url = "http://service4/test"; ResponseEntity<String> entity = restTemplate.getForEntity(url, String.class); //3 record end time long end = System.currentTimeMillis(); //4 Statistics time System.out.println("Time consuming:" + (end - start)); return entity; } /** * Handling method of fuse timeout * @return */ public ResponseEntity<String> dataFallback(){ return ResponseEntity.ok("Temporary data"); } }
1.4 interview questions: fuse + retry mechanism
- Interview question: if fuse and Ribbon retry mechanism are used in the project at the same time, who will execute first?
- If the time is different and the timeout is small, execute first
- If the time is the same, only the fuse is actuated
- Conclusion: if both need to be configured, the timeout of retry mechanism is less than that of fuse
2. Remote call
2.1, review
- HttpClient: Apache provides technology, which is more low-level, complete and cumbersome.
- RestTemplate: provided by Spring, easy to operate
2.2. Get to know Feign
- Feign for remote calls
- Features: declarative and modular HTTP client. When using remote call, it feels like "local method"
2.3. Introduction to Feign
- Step 1: modify pom file and add Feign dependency
<!--Remote call Feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- Step 2: modify the startup class and add the Feign annotation
@SpringBootApplication @EnableEurekaClient @EnableHystrix //Open fuse @EnableFeignClients //Feign open client public class ClientA9Application { public static void main(String[] args) { SpringApplication.run(ClientA9Application.class,args); } }
- Step 3: write Feign interface, complete remote call, replace dao layer
/** * @author Cloud before court * @Date 2019/12/11 11:40 * @description */ //FeignClient analysis @FeignClient(value = "service name",path = "controller prefix") public interface Interface name { //Consistent with controller method }
- Step 4: modify the controller and change the call dao to feign
/** * @author Cloud before court * @Date 2019/12/11 10:01 * @description */ @RestController @RequestMapping("/data") public class DataController { @Resource private DataFeign dataFeign; @GetMapping public ResponseEntity<String> data(){ return dataFeign.test(); } }