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!!