summarize
Hystrix provides a complete set of service isolation, service fusion and service degradation solutions for microservice architectures. It is an implementation of fuses, which are mainly used to solve the problems of high availability and service avalanche in microservice architectures
The features of Hystrix are as follows:
- Service Fuse: Hystrix fuse is like a safety valve at home, once a service is unavailable, the fuse will directly cut off the request on the link to avoid a large number of invalid requests affecting the stability of the system, and the fuse has a self-testing and recovery function, in the service state back to normal, it will be automatically shut down!
- Service Degradation: Hystrix implements service degradation through falback, defining a falback method in the class that needs to be degraded, so that when an exception occurs in the requested remote service, the fallback method can be used to return the exception information directly without invoking the remote service.
- Dependency isolation: Hyslrix achieves dependency isolation between services by means of thread pooling and signaling, so that even if one of the services has an exception and the resources cannot be released late, it will not affect the normal operation of other business threads.
- Thread Pooling Isolation Strategy: Hystrix Thread Pooling Resource Isolation allocates a thread pool for each dependent service, each thread pool handles a specific service, and the thread resources between multiple services do not affect each other to achieve the goal of resource isolation. When a dependent service is abnormal, only the thread resources of this dependent service will be blocked, not affecting other dependent services.
- The isolation strategy for semaphores: Hystrix The isolation strategy for semaphores is to assign a semaphore (atomic counter) to each dependent service, and when a request is made to a dependent service, determine if the semaphore value for that service exceeds the maximum value. If it exceeds the maximum value, the request will be discarded and an error message will be returned. If it doesn't exceed the maximum value, the request will be processed with the operation "Signal +1", and after the request is returned, the operation "Signal -1" will be performed.
- Request caching: Hystrix caches the request results according to the request parameters, so that when there is the same request later, it will not go through the complete call chain process again, but return the last cached result directly to achieve the purpose of fast service response and performance optimization. At the same time, the cache can be used as a data source for service degradation, when the remote service is not available, the cached data will be returned directly, for the consumer, it is just possible to get the outdated data, which elegantly handles the system exceptions.
- Request Merge: When a microservice needs to call multiple remote services to summarize the results, it needs to use request merging.Hystrix uses asynchronous message subscription for request merging.When an application needs to request multiple interfaces, it submits the request by asynchronous call and then subscribes to the return value.The application's business can then perform other tasks without blocking and waiting.When all the requests are returned, the application will get a notification and take out the return value to merge. When all the requests are returned, the application will get a notification, take out the return value and merge it.
Hystrix Service Degradation Process
- When a service request is made, a HystrixCommand command object is first created based on the annotations, which sets up the scenario in which the service invocation fails and the business logic methods for degrading the service after the invocation fails
- The fuse determines the state, and when the fuse is in the open state, the business logic method for service degradation is called directly to return feedback on the failure of the call
- When the fuse is in a semi-open or closed state, the service will check if there are available resources such as thread pools and semaphores, and if there are, it will invoke the normal business logic. If the invocation of the normal business logic succeeds, it returns the interest rate after success, if it fails, it invokes the degraded business logic to degrade the service
- When the fuse is half-open or closed, if there are no available resources in the current service thread pool and semaphore, the business logic of service degradation is executed and the call failure message is returned
- When the fuse is in the half-open state and this service execution fails, the fuse goes into the open state
- When normal business logic processing times out or an error occurs, HystrixCommand executes the service slowdown business-by-business and returns a call failure message.
- Resource checking and normal business logic for thread pools and semaphores feed their status and call results back to the monitor, which feeds the service status back to the fuser so that the fuser can determine the state of the fuse
Hystrix Applications
The use of Hystrix is divided into three main areas: service fusion, service degradation and service monitoring.
Introduce the Hystrix dependencies in the file, where spring-cloud-slarter-netflix-hystrix and hystrix-javanica are the dependencies required for Hystrix service fusion and spring-cloud-netflix-hystrix-dashboard is the dependency required for the dependency for Hystrix service monitoring
<dependency>
<groupId></groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>1.4.</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>hystrix-javanica</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId></groupId>
<artifactId>spring-cloud-netflix-hystrix-dashboard</artifactId>
<version>1.4.</version>
</dependency>
The @EnableHystrix annotation enables support for service fusion and the @EnableHystrixDashboard annotation enables support for service monitoring. Note that Hystrix is usually used in conjunction with service discovery, and @EnableEurekaClient enables support for service discovery clients.
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@EnableHystrixDashboard
public class HystrixServiceApplication {
public static void main(String[] args) {
(, args);
}
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Configuration File
#service name
=hystrix
#Port of the service
=9005
#Address of the registration center
=http://localhost:9001/eureka/
-fetch-interval-seconds=30
Service meltdown and degradation, define a remote call method hystrixHandler() and define a service degradation command on the method via @HystrixCommand(fallbackMethod="exceptionHandler"), when the remote method call fails, Hystrix will automatically invoke the fallbackMethod to fuse and demote the service, where the exceptionHandler method is called.
@Autowired
private RestTemplate restTemplate;
//Define the service downgrade command
@HystrixCommand(fallbackMethod = "exceptionHandler")
@RequestMapping(value = "/service/hystrix", method = )
public String hystrixHandler() {
return ("http://EUREKA-CLIENT/serviceProducer", ).getBody();
}
public String exceptionHandler() {
return "Provider services hung up";
}
asynchronous processing
The remote call request in the previous section must wait until the network request returns a result before executing the code that follows, i.e., blocking. In practice, applications often want to use non-blocking IO to achieve functionality more elegantly. Hyslrix provides two implementations of non-blocking IO, Future for future and Callable for callback.
1. Future
Define HystrixCommand
public class CommandFuture extends HystrixCommand<String> {
private String name;
private RestTemplate restTemplate;
public CommandFuture(String name, RestTemplate restTemplate) {
super((("ExampleGroup"))
//1:pass (a bill or inspection etc) HystrixCommandKey Name of the factory-defined dependency
.andCommandKey(("HelloWorld"))
//2:pass (a bill or inspection etc) HystrixThreadPoolKey Name of the factory-defined thread pool
.andThreadPoolKey(("HelloWorldPool")));
= name;
= restTemplate;
}
//3:Define the method body of the remote call
@Override
protected String run() {
String result = ("http://EUREKA-CLIENT/serviceProducer", ).getBody();
return result;
}
//4:Processing logic for service degradation
@Override
protected String getFallback() {
return "Remote Service Exception";
}
}
The above code defines a CommandFuture to implement asynchronous requests by inheriting HystrixCommand, where the logic for normal business execution is executed in the overridden run() method body, and the service degradation method is executed in getFallback(). Note that the use of andCommandKey(("HelloWorld")) implements the use of the HystrixCommandKey factory to define the names of the dependencies, where each CommandKey represents a dependency abstraction, and the same dependency uses the same CommandKey name. The essence of dependency isolation is that the same
CommandKey dependencies are segregated using andThreadPoolKey(("HelloWorldPool")) which implements a HystrixThreadPoolKey factory-defined thread pool name. When isolating resources from dependencies of the same service, use CommandGroup, but when different remote calls are made to the same dependency (e.g., one for a Redis service and one for an HTTP service), use HystrixThreadPoolKey to isolate them.
Using HystrixCommand
@RequeatMapping(value = "/service/hystrix/future", method = )
public String hystrixFutureHandler() throws ExecutionException, InterruptedException {
//Definitions are based onFutureasynchronous call,Requests are executed as a queue in the thread pool.
Future<String> future = new CommandFuture("future", restTemplate).queue();
return ();
}
2. Callable
A callback task is predefined. After the Callable issues a request, the main thread continues to execute, and after the request is executed and the result is returned, the Callable automatically calls the callback task.
Define HystrixObservableCommand
public class CommandObservable extends HystrixObservabCommand<String> {
private String name;
private RestTemplate restTemplate;
public CommandObservable(String nane, RestTemplate restTemplate) {
super(("ExampleGroup"));
= name;
= restTemplate;
}
//Observer Pattern Based Request Posting
@Override
protected Observable<String> construct () {
return (new <String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
try {
//Executing a Remote Procedure Call
if(!()) {
String result = ("http://EUREKA-CLIENT/serviceProducer", ).getBody();
//Pass down the result of the call
(result):
();
}
} catch(Exception e) {
();
(e);
}
}
}
}
//Processing logic for service degradation
@Override
protected Observable<String> resumeWithFallback() {
return (new <String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
try {
if(!()) {
("Remote Service Exception”);
();
} catch (Exception e) {
(e);
}
}
}
}
}
The above code defines a class named CommandObservable that inherits from the HystrixObservableCommand interface and implements the Observer pattern by overriding construct() in the HystrixObservableCommand interface. The implementation is to create and return an Observable via ().
Using the HystrixObservableCommand
public String hystrixCallableHandler() throws ExecutionException, InterruptedException {
List<String> list = new ArrayList<>();
// Define an asynchronous call based on inter-message ordering, where the result of the request is notified as an event.
Observable<String> observable = new CommandObservable("observer", restTemplate).observe();
// Clear request result subscription based on observer pattern
(new Observer<String>() {
// The onCompleted method is executed after all requests are completed @
@Override
public void onCompleted() {
("All requests have been completed...") ;
}
@Override
public void onError(Throwable throwable) {
();
}
// subscribe to the call event, where the request results converge, and collect the returned results in a collection
@Override
public void onNext(String s) {
("The results are coming...") ;
(s);
return ();
}
}
}
The above code defines a command that implements service publishing via new CommandObservable("observer", restTemplate).observe(). The subscription of request results based on the observer pattern is implemented by calling (), where the result of the subscribed data is notified in onNext() and the overall call result is notified in onCompleted(). The results of service handling exceptions are notified in onError().
Hystrix Dashboard
HystrixDashboard is mainly used for real-time monitoring of Hystrix operation indexes. HystrixDashboard allows you to query the real-time information of Hystrix, which can be used to quickly locate and discover problems. Hystrix Dashboard is simple and easy to use, first add the spring-cloud-netfix-hystrix-dashboard dependency to the file, then enable the Dashboard function by using the @ EnableHystrixDashboard annotation. Once the service is started, enter the following in the address bar of your browserhttp://127.0.0.1:9005/hystrix
You can see the monitoring interface