After learning about SpringCloud in the previous three sections, you learned that the provider of a service may have more than one port, and that in the future there may be more than one microservice to provide services in real work. If the service fails, if nothing is done, it can lead to serious losses.
For example, if you provide shopping services, it is impossible to get customers to buy things. And the most common example in life is when an electrical short circuit in the home, in order to ensure that the whole appliance, the fuse will be blown.
Hystrix was created to solve this problem.
1 introduction Hystrix
Establish hystrix parent module, modify the parent module POM file so that the child modules import dependencies, convenient for future operations.
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
</dependencies>
Copy the code
Then create a new hystrix-Consume9301 submodule under the parent module. The final project structure directory is as follows:
2 Main startup class and configuration file
Configuration file:
spring:
application:
name: hystrix-consume9301
server:
port: 9301
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:8001/eureka/
instance:
instance-id: hystrix-consume9301
Copy the code
In fact, the configuration file is simply the same, repeatedly written in order to facilitate CV reproduction
Main startup class:
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix / / open Hystrix
@RestController // Start the business class
public class HystrixConsume9301 {
public static void main(String[] args) { SpringApplication.run(HystrixConsume9301.class, args); }}Copy the code
3 business class
Again, to get started, it is not normal to write business classes directly in the main startup class.
In order to make calls between services, we talked about using RestTemplate in Eureka, so we need to add a Config class to inject RestTemplate into the Spring container.
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced // Enable load balancing, add this annotation to access the service by its name
public RestTemplate getRestTemplate(a) {
return newRestTemplate(); }}Copy the code
Back to the main launcher class
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix / / open Hystrix
@RestController // Start the business class
public class HystrixConsume9301 {
public static void main(String[] args) {
SpringApplication.run(HystrixConsume9301.class, args);
}
// Service name
final String PROVIDE_URL = "http://eureka-provide";
RestTemplate restTemplate;
public HystrixConsume9301(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping("/hystrix/consume")
@HystrixCommand(fallbackMethod = "getInfoFallback") // Enable the degraded service
public String getInfo(a) {
return "i am hystrix consumer, but actually invoke provide service: [" + restTemplate.getForObject(PROVIDE_URL + "/eureka/provide", String.class) + "]";
}
public String getInfoFallback(a) {
return "hello, something wrong, i am getInfo fallback method"; }}Copy the code
Everything else is the same, except that the @HystrixCommand annotation is added to the corresponding business method, and the fallbackMethod in this annotation declares which method to call back to if the service is degraded.
4 test
Open Eureka service registry EurekaServer8001, service provider EurekaProvide7001, [7002, 7003], and enable HystrixConsume9301
Visit http://localhost:9301/hystrix/consume, under normal circumstances as shown
But when we shut down all service providers EurekaProvide7001 to simulate a service failure, the test results are shown in the figure. You can see that the service does not report an error and does degrade the method we want to call.
5 extension
On the extension side, I’ll just mention the @hystrixProperty annotation a little bit and go straight to the example.
Service provider delay is simulated by the sleep() function
The first thing you need to change is the code on the service provider side, the service provider side, the service provider side. The Eureka-client-Provide7001 submodule project from the first article in this series
@SpringBootApplication
@RestController
@EnableEurekaClient
public class EurekaProvide7001 {
@Value("${server.port}")
int port;
@GetMapping("/eureka/provide")
public String getInfo(a) {
return "hello, i am eureka provide, the provide service. My port: " + port;
}
// Here are the additions
@GetMapping("/eureka/delayProvide")
public String delayGetInfo(a) throws InterruptedException {
Thread.sleep(3000);
// The real business logic is executed 3 seconds late
return "hello, delay to do something";
}
public static void main(String[] args) { SpringApplication.run(EurekaProvide7001.class, args); }}Copy the code
Then modify the code on the Hystrix consumer side
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
@RestController
public class HystrixConsume9301 {
public static void main(String[] args) {
SpringApplication.run(HystrixConsume9301.class, args);
}
final String PROVIDE_URL = "http://eureka-provide";
RestTemplate restTemplate;
public HystrixConsume9301(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
// omit part of it
@HystrixCommand(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000") }, fallbackMethod = "getPropFallback")
@GetMapping("hystrix/normalConsume")
public String getNormalConsumeInfo(a) {
long start = System.currentTimeMillis();
String res = restTemplate.getForObject(PROVIDE_URL + "/eureka/delayProvide", String.class);
long end = System.currentTimeMillis();
res += "[cost time: " + (end - start) + "]";
return res;
}
@HystrixCommand(commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000") }, fallbackMethod = "getPropFallback")
@GetMapping("hystrix/timeoutConsume")
public String getTimeoutConsumeInfo(a) {
long start = System.currentTimeMillis();
String res = restTemplate.getForObject(PROVIDE_URL + "/eureka/delayProvide", String.class);
long end = System.currentTimeMillis();
res += "[cost time: " + (end - start) + "]";
return res;
}
public String getPropFallback(a) {
return "timeout, fallback method, do something."; }}Copy the code
@ HystrixProperty (name = “execution. The isolation. Thread. TimeoutInMilliseconds”, value = “5000” mainly represents in the stipulated time (5000) if you can call service, So no fallback.
The above service was delayed 3000ms to execute the business, then I set a callback threshold of 5000ms and one of 2000ms.
Start the service provider EurekaProvide7001 before starting the test. It simulates a delay in calling the service, not a service failure. First of all, go to http://localhost:9301/hystrix/normalConsume:
It can be seen that the response after the rotation is about 3s, and the consumption time can also be seen.
So when accessing interface http://localhost:9301/hystrix/timeoutConsume: after overtime
You can see that the loop is about 2s after the response, and the fallback method is called, not the service provider method. In the previous case, it went to 3s because the service call was 3s, and in this case, it went to 2s because we set the callback threshold to 2s, after which fallback was called before the service was called.
6 Hystrix Dashboard
This is a visual monitor that helps us visually see some of Hystrix Command’s metrics for response
Introduction of depend on
Modify the POM file under the hystrix-Consume9301 submodule and add a dependency to it
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
Copy the code
Modify the main startup class to add beans
@SpringBootApplication
@EnableEurekaClient
@EnableHystrixDashboard // Open the visual interface, actually add this annotation
@EnableHystrix
@RestController
public class HystrixConsume9301 {}Copy the code
At this time can start main start class to visit http://localhost:9301/hystrix
See this interface configured successfully, it is worth noting that we also need to add a Bean configuration class can only be run correctly, a new kind of ServletRegisterBeanConfig under config package
@Configuration
public class ServletRegisterBeanConfig {
@Bean(name = "registerBean")
public ServletRegistrationBean getServlet(a){
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/actuator/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
returnregistrationBean; }}Copy the code
Finally restart HystrixConsume9301 main start class, visit http://localhost:9301/hystrix again, and then fill in the need to monitor the stream
When you click monitoring flow, an error occurs on the Dashboard interface and console at the same time
Modifying a Configuration File
Modify the control file according to the console error and add
hystrix:
dashboard:
proxy-stream-allow-list: localhost
Copy the code
Restart the project and repeat the above steps to see it running correctly. Wait for the connection
test
Open Eureka service registry EurekaServer8001, service provider EurekaProvide7001, [7002, 7003], and enable HystrixConsume9301. Access to consumer interface http://localhost:9301/hystrix/consume, http://localhost:9301/hystrix/normalConsume, http://localhost:9301/hystrix/timeoutConsume, can look at the monitor.
You can see that requests are indeed monitored in real time and have metrics.
Creation is not easy, if it is helpful to you, welcome to like, collect and share!
Below is a personal public number, interested can pay attention to, perhaps is your treasure public number oh, basic 2,3 days 1 more technical article!!