一、Hystrix 简介
Hystrix的设计原则是什么?
资源隔离(线程池隔离和信号量隔离)机制:限制调用分布式服务的资源使用,某一个调用的服务出现问题不会影响其它服务调用。
限流机制:限流机制主要是提前对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,不再调用后续资源。
熔断机制:当失败率达到阀值自动触发降级(如因网络故障、超时造成的失败率真高),熔断器触发的快速失败会进行快速恢复。
降级机制:超时降级、资源不足时(线程或信号量)降级 、运行异常降级等,降级后可以配合降级接口返回托底数据。
缓存支持:提供了请求缓存、请求合并实现
通过近实时的统计/监控/报警功能,来提高故障发现的速度
通过近实时的属性和配置热修改功能,来提高故障处理和恢复的速度
Hystrix是如何实现它的目标的?
(1)通过HystrixCommand或者HystrixObservableCommand来封装对外部依赖的访问请求,这个访问请求一般会运行在独立的线程中,资源隔离
(2)对于超出我们设定阈值的服务调用,直接进行超时,不允许其耗费过长时间阻塞住。这个超时时间默认是99.5%的访问时间,但是一般我们可以自己设置一下
(3)为每一个依赖服务维护一个独立的线程池,或者是semaphore,当线程池已满时,直接拒绝对这个服务的调用
(4)对依赖服务的调用的成功次数,失败次数,拒绝次数,超时次数,进行统计
(5)如果对一个依赖服务的调用失败次数超过了一定的阈值,自动进行熔断,在一定时间内对该服务的调用直接降级,一段时间后再自动尝试恢复
(6)当一个服务调用出现失败,被拒绝,超时,短路等异常情况时,自动调用fallback降级机制
(7)对属性和配置的修改提供近实时的支持
二、代码实现
搭建eureka注册中心上一篇文章已经介绍。
搭建订单服务生产者应用
maven依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fshows.cloud</groupId>
<artifactId>cloud-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- redis client -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.5</version>
</dependency>
<!--redis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- mysql drivers -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<!-- disruptor 用于log4j2的异步日志 -->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.3.6</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.2</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.2</version>
</dependency>
</dependencies>
订单服务启动类:注意订单服务启动类的注解 @EnableDiscoveryClient
@EnableDiscoveryClient
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
订单服务controller以及应用层代码实现:
@RequestMapping(value = "/getBankOrder",method = RequestMethod.GET)
public R<BankOrderDO> getOrderSn(@RequestParam("orderSn") String orderSn){
LOGGER.info("订单查询 >> getOrderSn >> orderSn = {}",orderSn);
BankOrderDO bankOrderDO = orderService.getBankOrderByOrderSn(orderSn);
return new R<>(bankOrderDO);
}
public BankOrderDO getBankOrderByOrderSn(String orderSn) {
return bankOrderDAO.getBankOrderByOrderSn(orderSn);
}
订单服务消费实现:
maven配置:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fshows.cloud</groupId>
<artifactId>cloud-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</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-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-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
</dependencies>
启动类代码注意订单服务启动类的注解 :@EnableFeignClients @EnableCircuitBreaker @EnableDiscoveryClient
@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
@EnableFeignClients
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class FeignConsumeApplication {
public static void main(String[] args) {
SpringApplication.run(FeignConsumeApplication.class, args);
}
}
订单服务的具体实现:
@FeignClient(value = "order-application",fallback = OrderClientFallback.class)
public interface OrderClient {
@RequestMapping(value = "/getBankOrder",method = RequestMethod.GET)
R<BankOrderDO> getBankOrder(@RequestParam("orderSn") String orderSn);
}
**
* 熔断机制处理类
* @author zhutr
* @version OrderClientServiceImpl.java, v 0.1 2019-08-03 17:20
*/
@Component
public class OrderClientFallback implements OrderClient {
/**
* 熔断机制处理代码
* @param orderSn
* @return
*/
@Override
public R<BankOrderDO> getBankOrder(String orderSn) {
CommonResponseEnum.SERVER_ERROR.newException();
return null;
}
}