Hystrix circuit breaker

An overview of the

Hystrix is an open source library for handling latency and fault tolerance in distributed systems, where many dependencies inevitably fail, such as timeouts and exceptions. Hystrix can ensure that the entire service does not fail in the event of a dependency failure, avoiding cascading failures. To improve the resiliency of distributed systems. ** The circuit breaker itself is a switching device. When a service unit fails, the fault monitoring of the circuit breaker (similar to blowing a fuse) returns an expected and manageable FallBack response to the calling method, rather than waiting for a long time or throwing an exception that the calling method exception cannot handle. This ensures that the threads of the service caller are not tied up unnecessarily for long periods of time, thus preventing the spread of failures in a distributed system.

Service fusing

Circuit breaker is a kind of micro avalanche effect of service link protection mechanism, when a fan out links micro service is not available or the response time is too long, will be carried out in the service’s downgrade, and fusing the node micro service invocation, rapid response information, return to the “wrong” when detected the node micro service invocation response after normal recovery call link, The circuit breaker mechanism in the SpringCloud framework is implemented using Hystrix, which monitors microservice calls when failures reach a certain threshold. It triggers a circuit breaker, which is annotated @hystrixCommand

Hystrix real fuck

Establish the microServicecloud-provider-dept-Hystrix-8001 project by referring to microServicecloud-provider-dept-8001

Pom. The XML file

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
Copy the code
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.luo.springcloud</groupId>
    <artifactId>microservicecloud</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
  </parent>
  <artifactId>microservicecloud-provider-dept-hystrix-8001</artifactId>
<dependencies>
		<! -- hystrix -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<! Dept Entity --> Dept Entity --> Dept Entity
		<dependency>
			<groupId>com.luo.springcloud</groupId>
			<artifactId>microservicecloud-api</artifactId>
			<version>${project.version}</version>
		</dependency>
		<! -- Actuator Monitoring Information Complete -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<! Register microservice provider with eureka -->
		<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>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
		</dependency>
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-core</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jetty</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
		</dependency>
		<! -- The modification takes effect immediately, hot deployment -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
	</dependencies>

</project>
Copy the code

Application. Yml file

eureka:
  client: Register the client in the Eureka service list
    service-url: 
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/      
  instance:
    instance-id: microservicecloud-dept8001-hystrix # Customize service name information
    prefer-ip-address: true     Access path can display IP address
Copy the code
server:
  port: 8001
  
mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml        # mybatis configuration file path
  type-aliases-package: com.luo.springcloud.entities        Package for all Entity alias classes
  mapper-locations:
  - classpath:mybatis/mapper/**/*.xml                       # mapper mapping file
    
spring:
   application:
    name: microservicecloud-dept 
   datasource:
    type: com.alibaba.druid.pool.DruidDataSource            The current data source operation type
    driver-class-name: org.gjt.mm.mysql.Driver              Mysql driver package
    url: jdbc:mysql://localhost:3306/cloudDB01              # database name
    username: root
    password: 1234
    dbcp2:
      min-idle: 5                                           The minimum number of sustained connections in the database connection pool
      initial-size: 5                                       Initialize the number of connections
      max-total: 5                                          # Maximum number of connections
      max-wait-millis: 200                                  Maximum timeout to wait for connection acquisition
      
eureka:
  client: Register the client in the Eureka service list
    service-url: 
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/      
  instance:
    instance-id: microservicecloud-dept8001-hystrix # Customize service name information
    prefer-ip-address: true     Access path can display IP address
    
info: 
  app.name: luokangyuan-microservicecloud
  company.name: www.luokangyuan.com
  build.artifactId: $project.artifactId$
  build.version: $project.version$
Copy the code

Modify DeptController

The purpose of Hystrix is to solve the problem when an exception occurs in the invocation of the service. It is simulated to check the department information based on the ID, find null, and manually throw a runtime exception, and let Hystrix handle the situation.

@RequestMapping(value="dept/get/{id}",method=RequestMethod.GET)
@HystrixCommand(fallbackMethod = "processHystrix_GET")
public Dept get(@PathVariable("id") Long id){
  Dept dept = service.get(id);
  if(null == dept){
    throw new RuntimeException("The ID."+id+"No corresponding department information.");
  }
  return dept;
}

public Dept processHystrix_GET(@PathVariable("id") Long id){
  return new Dept().setDeptno(id)
    .setDname("ID:"+id+"No corresponding information, null--@HystrixCommand")
    .setDb_source("no this database in Mysql");
}
Copy the code

Modify the main startup class to add Hystrix support

@SpringBootApplication
@EnableEurekaClient // The service will be registered with the Eureka Service Registry once it is started
@EnableDiscoveryClient // Service discovery
@EnableCircuitBreaker // Support for Hystrix circuit breakers
public class DeptProvider8001_Hystrix_App {
	public static void main(String[] args) { SpringApplication.run(DeptProvider8001_Hystrix_App.class, args); }}Copy the code

Test circuit breaker mechanism

Start three Eureka clusters, start the service main startup class DeptProvider8001_Hystrix_App, start the client microServicecloud-consumer-dept-80, Page to http://localhost/consumer/dept/get/112

Service degradation

Service degradation is done on the client side, independent of the server side. In the previous service meltdown, we found that each business method writes a processHystrix_ method, which creates a lot of coupling. Based on Spring’s learning, we can override processHystrix_ as an exception notification.

Modify the MicroServicecloud-API project

According to the existing DeptClientService interface, an implementation of a new class DeptClientServiceFallbackFactory FallbackFactory interface

package com.luo.springcloud.service;

import java.util.List;

import org.springframework.stereotype.Component;

import com.luo.springcloud.entities.Dept;

import feign.hystrix.FallbackFactory;
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService>{

	@Override
	public DeptClientService create(Throwable arg0) {
		return new DeptClientService() {
			
			@Override
			public List<Dept> list(a) {
				return null;
			}
			
			@Override
			public Dept get(long id) {
				return new Dept().setDeptno(id)
						.setDname("ID:"+id+"The service is suspended without corresponding information about the downgrade provided by the Consumer client.")
						.setDb_source("no this database in Mysql");
			}
			
			@Override
			public boolean add(Dept dept) {
				return false; }}; }}Copy the code

Note: Don’t forget to add the @Component annotation to the new class

Modify microservicecloud – API

Add the fallbackFactory attribute value to the @feignClient (value = “microServicecloud-dept “) annotation in the DeptClientService interface

@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
Copy the code
@FeignClient(value = "MICROSERVICECLOUD-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
	@RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
	public Dept get(@PathVariable("id") long id);
	
	@RequestMapping(value = "/dept/list",method = RequestMethod.GET)
	public List<Dept> list(a);
	
	@RequestMapping(value = "/dept/add", method = RequestMethod.POST)
	public boolean add(Dept dept);
}
Copy the code

Modify the Application. Yml file of microServicecloud-consumer-dept-feign

server:
  port: 80
  
feign: 
  hystrix: 
    enabled: true
eureka:
  client:
    register-with-eureka: false
    service-url: 
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/  
Copy the code

Test service degradation

Start three Eureka clusters, microServicecloud-provider-dept-8001, microServicecloud-consumer-dept-Feign, microServicecloud-consumer-dept-Feign Normal visit http://localhost/consumer/dept/get/1 test, deliberately shut down microservicecloud – the provider – dept – 8001, the client himself call reminder

Service monitoring Hystrix Dashboard

Hystrix also provides a quasi-real-time call monitoring Hystrix Dashboard. Hystx continuously records the execution information of all requests initiated by Hystrix and presents it to users in the form of graphs and statistical reports, including the number of requests executed per second, the number of successful requests, and the number of failures. To monitor the content into a visual interface.

Create a microservice project monitored by the MicroServicecloud-Consumer-Hystrix-Dashboard

POM. The XML file

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.luo.springcloud</groupId>
    <artifactId>microservicecloud</artifactId>
    <version>0.0.1 - the SNAPSHOT</version>
  </parent>
  <artifactId>microservicecloud-consumer-hystrix-dashboard</artifactId>
<dependencies>
		<! -- self-defined API -->
		<dependency>
			<groupId>com.luo.springcloud</groupId>
			<artifactId>microservicecloud-api</artifactId>
			<version>${project.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<! -- The modification takes effect immediately, hot deployment -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>springloaded</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
		</dependency>
		<! -- Ribbon related -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-eureka</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<! -- Feign related -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
		</dependency>
		<! -- Hystrix and Hystrix-Dashboard -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
		</dependency>
	</dependencies>
</project>
Copy the code

Application. Yml file

server:
  port: 9001
Copy the code

The main boot class DeptConsumer_DashBoard_App

@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {
	public static void main(String[] args) { SpringApplication.run(DeptConsumer_DashBoard_App.class, args); }}Copy the code

The microservice provider adds a monitoring dependency configuration

All Provider microservice Provider classes (8001,8002,8003) need to monitor dependency configurations, that is, add the following dependencies to pom files

<! -- Actuator Monitoring Information Complete -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Copy the code

Monitoring page test

Start microservicecloud – consumer – hystrix – dashboard, visit http://localhost:9001/hystrix, a porcupine page

All test

Start 3 Eureka clusters, start MicroServicecloud-provider-dept-Hystrix-8001, Launched microservicecloud – consumer – hystrix – dashboard to monitor 8001 service providers, visit http://localhost:8001/hystrix.stream

Observation monitoring window

Visit http://localhost:9001/hystrix to monitor the address http://localhost:8001/hystrix.stream, 2000, the title: demo01, click on the button

Solid round: The healthy color is decreasing from green < yellow < orange < red. In addition to the color change, the size of the solid circle will also change according to the request flow of the instance. The larger the flow, the larger the solid circle will be. Therefore, the display of solid circles can quickly find fault instances and high pressure test in a large number of instances.