作者:jiangzz
电话:15652034180
微信:jiangzz_wx
微信公众账号:jiangzz_wy
Hystrix is a delay and fault-tolerant database, designed to isolate the access point to remote systems, services and third-party libraries, stop cascading failure, and to achieve flexibility in complex distributed systems, in these systems, failure is inevitable .
Introduce the following dependence
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
SpringBootApplication entrance need to add @EnableCircuitBreaker
notes, then Spring AOP factory will start on the way there are all methods @HystrixCommand
to add fuse strategic business approach.
@SpringBootApplication
@EnableCircuitBreaker
@MapperScans(value = {@MapperScan(basePackages = {"com.jiangzz.dao"})})
public class HystrixSpringBootApplication {
public static void main(String[] args) {
SpringApplication.run(HystrixSpringBootApplication.class,args);
}
}
Add on business method @HystrixCommand
Notes realized blown.
@HystrixCommand
@Override
public User queryUserById(Integer id) {
System.out.println(Thread.currentThread().getId());
return userDAO.queryById(id);
}
Thread isolation
The default method of execution will start a new thread of execution and the main program is not a thread, so if there is ThreadLocal variable context, in this method becomes ineffective. So generally annotation property by setting commandProperties, set the thread on it.
@HystrixCommand(commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy",value = "SEMAPHORE")
})
@Override
public User queryUserById(Integer id) {
System.out.println(Thread.currentThread().getId());
return userDAO.queryById(id);
}
execution.isolation.strategy
Optional value of the property has twoTHREAD
andSEMAPHORE
the default value isTHREAD
.① general if there is a second instance of a 100 concurrent, this time because of frequent start threads overhead is too large at this time generally consider SEMAPHORE, ② non-network calls.
Fallback
S name in @HystrixCommand declared fallbackMethod can achieve graceful degradation, as follows:
@HystrixCommand(fallbackMethod = "fallbackMethodQueryUserById")
@Override
public User queryUserById(Integer id) {
System.out.println(Thread.currentThread().getId());
int i=10/0;
return userDAO.queryById(id);
}
public User fallbackMethodQueryUserById(Integer id, Throwable e) {
System.out.println(e.getMessage());
return new User();
}
Note that the target method and the method in claim fallbackMethod must be in the same class having the same parameters (abnormal parameter optional)
Error Propagation
According to this description, @ HystrixCommand able to specify the type of exception should be ignored. The following ArithmeticException: / by zero
will not trigger fallbackMethod method.
@HystrixCommand(fallbackMethod = "fallbackMethodQueryUserById",ignoreExceptions = {ArithmeticException.class})
@Override
public User queryUserById(Integer id) {
System.out.println(Thread.currentThread().getId());
int i=10/0;
return userDAO.queryById(id);
}
public User fallbackMethodQueryUserById(Integer id, Throwable e) {
System.out.println(e.getMessage());
return new User();
}
Request timed out fuse
The user can set the execution.isolation.thread.timeoutInMilliseconds
property of a requested maximum delay method, the system will throwHystrixTimeoutException
@HystrixCommand(fallbackMethod = "fallbackMethodQueryUserById",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="100")
})
@Override
public User queryUserById(Integer id) {
return userDAO.queryById(id);
}
public User fallbackMethodQueryUserById(Integer id, Throwable e) {
System.out.println(e);
return new User();
}
For more information, please refer to:
https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica
https://github.com/Netflix/Hystrix/wiki/Configuration
Hystrix Dashboard
Add the following items dependent
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Add SpringBoot inlet class @EnableHystrixDashboard
annotated as follows
@SpringBootApplication
@MapperScans(value = {@MapperScan(basePackages = {"com.jiangzz.dao"})})
@EnableCircuitBreaker
@EnableHystrixDashboard
public class SpringBootApplicationDemo {
public static void main(String[] args) {
SpringApplication.run(SpringBootApplicationDemo.class,args);
}
}
Application.properties modify the configuration file as follows
# 配置数据源
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
## MyBatis DAO
mybatis.type-aliases-package=com.jiangzz.entities
mybatis.mapper-locations=classpath*:mappers/*.xml
## 打印SQL
logging.level.root=info
logging.level.org.springframework.jdbc=debug
logging.level.com.jiangzz.dao=trace
spring.application.name=USER-SERVICE
eureka.instance.instance-id=001
eureka.instance.prefer-ip-address=true
eureka.instance.lease-expiration-duration-in-seconds=20
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.client.register-with-eureka=true
eureka.client.healthcheck.enabled=true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://jiangzz:123456@localhost:8761/eureka/
management.endpoints.web.exposure.include=*
Service code as modified UserService
@Service
@Transactional(propagation = Propagation.SUPPORTS)
public class UserService implements IUserService {
@Autowired
private IUserDAO userDAO;
@HystrixCommand(fallbackMethod = "fallbackMethodQueryUserById",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="100")
})
@Override
public User queryUserById(Integer id) {
return userDAO.queryById(id);
}
public User fallbackMethodQueryUserById(Integer id, Throwable e) {
System.out.println(e);
return new User();
}
}
Access the page http: // localhost: 8080 / hystrix
click on the Monitor Stream
button to view monitoring status