1 Hystrix简介
1.1 分布式系统面临的问题
1.2 Histrix是什么
1.3 Hystrix能做什么
服务降级、服务熔断,接近实时监控。
官方文档:https://github.com/Netflix/Hystrix/wiki
1.4 停更运维
后面我们会介绍代替的方案,但是必须先学习Hystrix了解其思想。
2.Hystix的重要概念
2.1 服务降级
概念:服务降级一般是指在服务器压力剧增的时候,根据实际业务使用情况以及流量,对一些服务和页面有策略的不处理或者用一种简单的方式进行处理,从而 释放服务器资源的资源以保证核心业务的正常高效运行。
原因: 服务器的资源是有限的,而请求是无限的。在用户使用即并发高峰期,会影响整体服务的性能,严重的话会导致宕机,以至于某些重要服务不可用。故高峰期为了保证核心功能服务的可用性,就需要对某些服务降级处理。可以理解为舍小保大
应用场景: 多用于微服务架构中,一般当整个微服务架构整体的负载超出了预设的上限阈值(和服务器的配置性能有关系),或者即将到来的流量预计会超过预设的阈值时(比如双11、6.18等活动或者秒杀活动)
总结:服务降级是舍小保大,释放服务器资源的资源以保证核心业务的正常高效运行。
2.2 服务熔断
熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。
这种牺牲局部,保全整体的措施就叫做熔断。
总结:服务熔断相当于断闸
❤服务降级与服务熔断的区别
1.触发原因不一样,服务熔断由链路上某个服务引起的,服务降级是从整体的负载考虑
2.管理目标层次不一样,服务熔断是一个框架层次的处理,服务降级是业务层次的处理
3.实现方式不一样,服务熔断一般是自我熔断恢复,服务降级相当于人工控制
4.触发原因不同 服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
总结:服务熔断是应对系统服务雪崩的一种保险措施,给出的一种特殊降级措施。而服务降级则是更加宽泛的概念,主要是对系统整体资源的合理分配以应对压力。
2.3服务限流
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说系统的吞吐量是可以被测算的,为了保证系统的稳定运行,一旦达到的需要限制的阈值,就需要限制流量并采取一些措施以完成限制流量的目的。比如:延迟处理,拒绝处理,或者部分拒绝处理等等
总结:服务限流相当于排队
3 Hystrix微服务构建
3.1 准备工作
前面我们使用的都是Eureka集群,为了简化后面的测试、编码工作,避免每次启动的微服务数量过多(方便学习演示),我们暂时将7001的application.yml改造下,改成单机环境。
3.2 建项目
新建项目cloud-provider-hystrix-payment8001
3.3 写pom
<dependencies> <!-- hystrix--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <!-- 引用自己定义的api通用包,可以使用Payment支付Entity --> <dependency> <groupId>com.wangzhou.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <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> <!--eureka client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!--热部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- 一个Java工具包 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
3.4 写yml
server: port: 8001 spring: application: name: cloud-provider-hystrix-payment eureka: client: register-with-eureka: true fetch-registry: true service-url: #单机版 defaultZone: http://localhost:7001/eureka #集群版 # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
3.5 主启动
@SpringBootApplication @EnableEurekaClient public class PaymentHystrixMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentHystrixMain8001.class, args); } }
3.6 业务类
(1)Service
节约时间,我们就不写接口了。
@Service public class PaymentService { // 正常访问 public String paymentInfo_OK(Integer id){ // Hystrix底层调用的是Tomcat的线程池,我们在这里将线程名放回 return "线程: "+Thread.currentThread().getName()+" paymentInfo_OK, id = "+id; } //超时访问 public String paymentInfo_Timeout(Integer id) throws InterruptedException { int timeout = 3; // Hystrix底层调用的是Tomcat的线程池,我们在这里将线程名放回 TimeUnit.SECONDS.sleep(timeout); return "线程: "+Thread.currentThread().getName()+" paymentInfo_OK, id = "+id + "\t" + "耗时"+ timeout +"s"; } }
(2)Controller
@RestController @Slf4j public class PaymentController { @Resource private PaymentService paymentService; @Value("${server.port}") private String serverPort; @GetMapping("/payment/hystrix/ok/{id}") public String paymentOk(@PathVariable("id")Integer id) { String result = paymentService.paymentInfo_OK(id); log.info("result:" + result); return result; } @GetMapping("/payment/hystrix/timeout/{id}") public String paymentInfo_timeout(@PathVariable("id") Integer id) throws InterruptedException { String result = paymentService.paymentInfo_Timeout(id); log.info("********* RESULT:"+ result +"***********"); return result; } }
3.7 测试
启动7001,8001两个微服务。
访问:http://localhost:7001/,可用看到带熔断的8001Hystrix微服务。
访问ok接口
http://localhost:8001/payment/hystrix/ok/1
没毛病。
timeout接口。