Spring cloud's Hystrix and service monitoring Dashboard for dealing with avalanche effect

Article directory

Preface

This chapter is no longer a configuration file as before, but a case study of how to deal with avalanche effect.

Because avalanche effect refers to the server, it's OK to have a good understanding of the server.

The concept and reason of avalanche effect

Avalanche effect

What is avalanche effect?
As a matter of fact, it may be half understood that the defect of one point causes the problem to become bigger and bigger.
In fact, that's it.

Here's a chestnut:

1. A request from a to find service a, but service a can't solve the demand of request A. at this time, service B also receives the request from B, but the processing method of service B requires service a to process a part, but service a is still processing a request, unable to give service B a reply.


2. At the same time, service A will receive other requests for service A at this time, so service A hangs up in the request backlog, so service B can't give A reply, so service B is stuck until it goes down

3. Similarly, if there is service C that needs to rely on service B, then...

Cause
The reasons are as follows:

There are several common avalanches:

  • Program bug causes the service to be unavailable or run slowly
  • The cache breaks down, causing all calls to access a service, causing a down
  • A sudden surge in traffic.
  • Hardware issues,

Well, there are many reasons,

Using the Hystrix processing strategy

In fact, it will work. After all, it's a perfect solution,

Principle: after the service exceeds the time of the Hystrix policy, the policy will automatically demote the request. In fact, demotion means that the method you want to request cannot be requested, so you call the specified method and directly return a busy server to achieve the effect of fusing (that is, to disconnect the request line)

1. Import Hystrix dependency
2. Add @ EnableCircuitBreaker to the service side to process the scenario
3. You can modify the default timeout of Hystrix in the yml file

Hystrix case

Create a server to prepare the simulation test: microservice-student-provider-hystrix-1004

pom.xml
Add a Hystrix dependency

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <!--Keep the version used consistent1.0-SNAPSHOT-->
  <parent>
    <groupId>com.wxm</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>microservice-student-provider-hystrix-1004</artifactId>

  <properties>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <!--Equivalent to a global dependency, this import ensures that the package versions used in the whole project are consistent
        For example, in the overall situation: spring-cloud-dependencies
                       spring-boot-dependencies
                       druid-spring-boot-starter

    -->
    <dependency>
      <groupId>com.wxm</groupId>
      <artifactId>microservice-common</artifactId>
    </dependency>
    <!--Handle web request-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--test Test packages-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <!--The database relational mapping framework used is jpa-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!--Used is mysql data base-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--Use tomcat-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-tomcat</artifactId>
    </dependency>
    <!--druid data source-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
    </dependency>
    <!--  Effective immediately after modification, hot deployment  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>springloaded</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <!--Entity classes that need to import common modules, etc. (appear when importing)-->
    <dependency>
      <groupId>com.wxm</groupId>
      <artifactId>microservice-common</artifactId>
      <version>1.0-SNAPSHOT</version>
      <scope>compile</scope>
    </dependency>
    <!-- actuator Monitoring introduction and accountability after clicking -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--Add registry Eureka Related configuration,That is to say, this is the client-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <!--Hystrix Dependent dependence,Used to handle service handling exceptions-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>




  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>

</project>


A processing time policy of Hystrix is added to the yml file.

server:
  port: 1004
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:2206/context?useUnicode=true&characterEncoding=utf8
    username: root
    password: root
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application: # Set the basic information of the application(Name
    name: microservice-student

eureka:
  instance:
    hostname: localhost  #eureka client host instance name
    appname: microservice-student  #Client service name
    instance-id: microservice-student:1004 #Client instance name
    prefer-ip-address: true #Show IP or not
  client:
    service-url:
      #Set the address to interact with Eureka registry, which is all registries
      defaultZone: http://eureka2001.wxm.com:2001/eureka/,http://eureka2002.wxm.com:2002/eureka/,http://eureka2003.wxm.com:2003/eureka/   #Register the service with the eureka registry

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000

info:
  groupId: com.wxm.springcloud
  artifactId: microservice-student-provider-1004
  version: 1.0-SNAPSHOT
  userName: http://www.wxm.com
  phone: 123456

Changes of main class

package com.wxm.microservicestudentproviderhystrix1004;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.EnableMBeanExport;

@EnableCircuitBreaker
@EntityScan("com.wxm.*.*")
@SpringBootApplication
public class MicroserviceStudentProviderHystrix1004Application {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceStudentProviderHystrix1004Application.class, args);
    }

}

Important Controller layer

Here we add a request method for hystrix

package com.wxm.microservicestudentproviderhystrix1004.controller;

import com.wxm.microservicestudentproviderhystrix1004.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/student")
public class StudentProviderController {

    @Value("${server.port}")
    private String port;


    @Autowired
    private StudentService studentService;
     
    @PostMapping(value="/save")
    public boolean save(Student student){
        try{
            studentService.save(student);  
            return true;
        }catch(Exception e){
            return false;
        }
    }
     
    @GetMapping(value="/list")
    public List<Student> list(){
        return studentService.list();
    }
     
    @GetMapping(value="/get/{id}")
    public Student get(@PathVariable("id") Integer id){
        return studentService.findById(id);
    }
     
    @GetMapping(value="/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id){
        try{
            studentService.delete(id);
            return true;
        }catch(Exception e){
            return false;
        }
    }

    @RequestMapping("/ribbon")
    public String ribbon(){
        return "Job number ["+port+"]Serving you";
    }

    /**
     * Test Hystrix service degradation
     * @return
     * @throws InterruptedException
     */
    @GetMapping(value="/hystrix")
    @HystrixCommand(fallbackMethod="hystrixFallback")
    public Map<String,Object> hystrix() throws InterruptedException{
        Thread.sleep(3000);
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("code", 200);
        map.put("info","Job number ["+port+"]Serving you aaaa");
        return map;
    }

    public Map<String,Object> hystrixFallback() throws InterruptedException{
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("code", 500);
        map.put("info", "System ["+port+"]Busy, try again later");
        return map;
    }
}


be careful!!! We should also add this request to the previous consumers

   /**
     * Test Hystrix service degradation
     * @return
     */
    @GetMapping(value="/hystrix")
    public Map<String,Object> hystrix(){
        return restTemplate.getForObject(SERVER_IP_PORT+"/student/hystrix/", Map.class);
    }

test

Then we can simulate a service request timeout problem according to the simulated sleep time.
The default timeout for Hystrix is 1 second.

You can modify the time policy of Hystrix

Effect

##Dashboard, the service monitoring platform of Hystrix

The key point is to monitor the service status of the corresponding port number
Create a project: microservice-student-consumer-hystrix-dashboard-90

pom.xml dependency
Just rely on what you need

yml file:

server:
  port: 90
  context-path: /

main

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@EnableHystrixDashboard
public class MicroserviceStudentConsumerHystrixDashboard90Application {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceStudentConsumerHystrixDashboard90Application.class, args);
    }

}

After opening, enter your own address http://localhost:90/hystrix

Click ok to display the following interface:

summary

1. The principle of avalanche
2. Strategies for dealing with avalanches: a solution strategy, Hystrix
3. Service monitoring platform: Dashboard

1, What is avalanche effect?
As a matter of fact, it may be half understood that the defect of one point causes the problem to become bigger and bigger.
In fact, that's it.
Here's a chestnut:
1. A request from a to find service a, but service a can't solve the demand of request A. at this time, service B also receives the request from B, but the processing method of service B requires service a to process a part, but service a is still processing a request, unable to give service B a reply.

2. At the same time, service A will receive other requests for service A at this time, so service A hangs up in the request backlog, so it is even more unable to give A reply to service B, so service B is stuck until it goes down.

3. Similarly, if there is service C that needs to rely on service B, then...

2, Handling strategy Hystrix
In fact, it will work. After all, it's a perfect solution,

Principle: after the service exceeds the time of the Hystrix policy, the policy will automatically demote the request. In fact, demotion means that the method you want to request cannot be requested, so you call the specified method and directly return a busy server to achieve the effect of fusing (that is, to disconnect the request line)

1. Import Hystrix dependency
2. Add @ EnableCircuitBreaker to the service side to process the scenario
3. You can modify the default timeout of Hystrix in the yml file

Three. Service monitoring platform

There's nothing to say about this. The point is that the service status of the corresponding port number can be monitored

Conclusion: this operation is very simple. The main point is to understand the avalanche effect and deal with it

Published 100 original articles, won praise 8, visited 4032
Private letter follow

Tags: Spring Maven Java MySQL

Posted on Sun, 12 Jan 2020 05:56:34 -0800 by shaitand