SpringCloud-Hystrix简单配置和使用
Hystrix官方文档: Introduction · Hystrix Document (gitbooks.io)
一.简介说明
Hystrix 供分布式系统使用,提供延迟和容错功能,隔离远程系统、访问和第三方程序库的访问点,防止级联失败,保证复杂的分布系统在面临不可避免的失败时,仍能有其弹性。
在分布式环境中,不可避免会造成一些服务的失败。Hystrix库旨在控制分布式服务中提供更大容限和服务失败之间的相互关系。Hystrix通过隔离访问远程系统、服务和第三方库的点,阻止级联故障,从而使复杂的分布式系统更具弹性。
“断路器” 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。
可以干嘛?
- 服务熔断
- 服务降级
- 服务限流
- 接近实时的监控
- …
二.服务熔断
1.什么是服务熔断?
百度百科解释: 服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
简单的说就是当某服务链路中的某个服务突然间发生了异常导致调用时间过长或者服务不可用,这时如果不及时响应处理,在高并发高流量的请求下,可能会导致此异常服务占据大量资源进而使其他服务无法正常运行,最终只会走向服务雪崩,而熔断机制由此产生,我们可以通过服务熔断,在服务异常时,对服务进行降级,即不正常调用,调用Hystrix的熔断方法,快速返回错误的响应信息,当检测到该节点正常后,微服务恢复原链路的调用,进而实现熔断效果。
熔断机制的注解: @HystrixCommand
2.配置和使用
服务熔断是在provider端中进行配置的
在provider的pom.xml中添加依赖
<!-- 导入hystrix依赖包 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
启动类上中开启熔断,即添加@EnableCircuitBreaker注解
package com.laoliu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient //开启Eureka客户端
@EnableDiscoveryClient //发现所有的服务
@EnableCircuitBreaker //开启熔断机制
public class DeptProviderHystrix8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix8001.class);
}
}
修改Controller中的方法(示例)
package com.laoliu.springcloud.controller;
import com.laoliu.springcloud.pojo.Dept;
import com.laoliu.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/dept")
public class DeptController {
@Autowired
private DeptService deptService;
//一旦调用服务方法失败并抛出了错误信息后
// 会自动调用HystrixCommand标注好的fallbackMethod调用类中指定方法
@GetMapping("/get/{id}")
@HystrixCommand(fallbackMethod = "throwHystrix_Get")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if (dept == null){
throw new RuntimeException("该id没有相应信息");
}
return dept;
}
public Dept throwHystrix_Get(@PathVariable("id") Long id){
return new Dept().setDeptno(id)
.setDbSource("数据库没有该库源")
.setDname("该id=>"+id+"没有对应信息,null-->@HystrixCommand");
}
}
启动Eureka注册中心,该provider提供者服务和consumer消费者服务,调用接口并查看,结果如下:
三.服务降级
1.什么是服务降级?
百度百科解释: 服务降级是当服务器压力剧增的情况下,根据当前业务情况及流量对一些服务和页面有策略的降级,以此释放服务器资源以保证核心任务的正常运行。
举例简单说,一个系统中有一个主要服务流量请求高,一些次要服务流量低,某天主要服务请求突然增高,系统资源大量占用(资源甚至会不足),为了更好的优先处理该主要服务,主动先将一些次要服务进行关闭,并通知告知给客户,这就是服务降级(可以以淘宝双十一为例子,抢购和其他服务)
2.配置和使用
服务降级是在consumer端中进行配置使用的
在springcloud-api模块中,添加实现FallbackFactory的类DeptClientServiceFallbackFactory(名字自取):
package com.laoliu.springcloud.service;
import com.laoliu.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.List;
@Component //一定要加上
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
@Override
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept().setDeptno(id)
.setDname("Consumer提供了服务降级,此刻provider服务已经关闭")
.setDbSource("已经服务降级");
}
@Override
public boolean addDept(Dept dept) {
return false;
}
@Override
public List<Dept> queryAll() {
return null;
}
};
}
}
在DeptClientService接口中,@FeignClient添加fallbackFactory参数,参数为DeptClientServiceFallbackFactory类:
package com.laoliu.springcloud.service;
import com.laoliu.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
//value为服务实例名称,fallbackFactory为实现FallbackFactory接口的类
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id);
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
@GetMapping("/dept/list")
public List<Dept> queryAll();
}
springcloud模块的结构图如下:
在springcloud-consumer-dept-openFeign-80模块中添加相应依赖(包括hystrix和openFeign):
pom.xml
<dependencies>
// 刚刚实现的api模块
<dependency>
<groupId>com.laoliu</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--
springCloud2020 版本 把Bootstrap被默认禁用,
spring.config.import加入了对解密的支持。对于Config Client、Consul、Vault和Zookeeper的配置导入,
如果需要使用原来的配置引导功能,
那么需要将org.springframework.cloud:spring-cloud-starter-bootstrap依赖引入到工程中
这样才能正常使用springCloud
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- 导入OpenFeign依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 导入hystrix依赖包 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
在application中开启hystrix
server:
port: 80
# 旧版本
#feign:
# hystrix:
# enabled: true
# 新版本
feign:
circuitbreaker:
enabled: true
eureka:
client:
register-with-eureka: false # false 不是服务提供者,不需要注册到Eureka中
fetch-registry: true # true 消费者需要检索注册中心服务才能调用实例,否则找不到实例,调用失败,报错!!!!!
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
springcloud-consumer-dept-openFeign-80项目结构图如下:
模拟测试=>启动Eureka注册中心,provider提供者服务和该consumer消费者服务,调用接口并查看:
provider开启时,结果如下:
关闭provider后,继续请求,结果如下:
通过结果可以看出,provider关闭后,服务请求失败,consumer会通过OpenFeign和Hystrix模拟相应信息告知用户!以此实现服务降级
三.服务监控
Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会持续地记录所有通过Hystrix发起的请求的执行信息,并以统计报表和图形的形式展示给用户,包括每秒执行多少请求,多少成功,多少失败等等。
配置和使用
新建模块工程springcloud-consumer-hystrix-dashboard-9001
在pom中导入spring-cloud-starter-netflix-hystrix-dashboard和spring-cloud-starter-netflix-hystrix依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>3.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<!-- 导入hystrix依赖包 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<!-- 导入hystrix-dashboard依赖 -->
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-hystrix-dashboard -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
在application中配置如下:
server:
port: 9001
# 需要配置,在新版中stream的监控列表中没有localhost,或者说没有该ip,
# 要手动添加地址,不然会监控不到,一直出现Unable to connect to Command Metric Stream.
hystrix:
dashboard:
proxy-stream-allow-list: "localhost"
没配置的情况下进行访问结果:
启动类中开启HystrixDashboard,添加注解@EnableHystrixDashboard:
package com.laoliu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboard9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboard9001.class,args);
}
}
启动该服务通过连接http://localhost:9001/hystrix/ 访问:
所有的provider服务中都需要监控依赖配置:
<!--actuator监控信息完善-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application中要将hystrix.stream服务打开
# 监控短点配置,springboot2.5以后,默认只开启health,需要手动打开其他
management:
endpoints:
web:
exposure:
include: "*" # 全部打开 如果单打开hystrix.stream只需将*改为hystrix.stream
以springcloud-provider-dept-hystrix-8001为例子,除了完善好spring-boot-starter-actuator配置后,在启动类中添加一个类如下:
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableCircuitBreaker
public class DeptProviderHystrix8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProviderHystrix8001.class);
}
//添加以下该bean,提供监控流,直接拿来用,不需要修改
@Bean
public ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServlet(){
ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
运行: 启动Eureka注册中心,springcloud-provider-dept-hystrix-8001提供者服务,consumer消费者服务,springcloud-consumer-hystrix-dashboard-9001监控服务
访问springcloud-provider-dept-hystrix-8001监控流可以看到实时ping中
将该路径填写到监控页面中:
还没请求时,不会出现监控列表,Cricuit和Thread Pools都是Loading中
发送请求后将可以看到监控列表:
注意:该监控列表的出现是实现了熔断机制的请求才能配合Hystrix监控,即添加了@HystrixCommand(fallbackMethod = “方法名”)注解的请求才能被监控
四.结语
上文若有错的地方请大佬不吝指出,我将进行改正和学习,最后感谢各位的观看!