hystrix 服务降级,熔断,限流
需求:高并发场景下,防止一个服务出错造成链式的雪崩/服务有限订的返回时间,hystrix常用在客户端,服务端也可以使用。
服务端:
1.pom
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.yml:
server:
port: 8001 #服务端口
spring:
application:
name: cloud-payment-service #服务名
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #数据库驱动包
url: jdbc:mysql://localhost:3306/cloud?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password: "000000"
mybatis:
type-aliases-package: com.cloud.util.entity
mapper-locations: classpath:mapper/*.xml
configuration:
cache-enabled: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
params: count=countSql
eureka:
client:
# 表示将自己注册到eureka服务中心去
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka
instance:
instance-id: payment8001
prefer-ip-address: true
3.main:
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class mainHystrix {
public static void main(String[] args) {
SpringApplication.run(mainHystrix.class,args);
}
}
4.service服务,配置一个兜底的方法,当服务超时或者报错的话,都会进入到timeoutHandler方法中去
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
})
public String timeOut() throws InterruptedException {
Thread.sleep(5000);
return "test";
}
public String timeoutHandler() throws InterruptedException {
return "fallback success";
}
客户端
5.yml:
server:
port: 80 #服务端口
eureka:
client:
# 表示将自己注册到eureka服务中心去
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
//ribbon:
//ReadTimeout: 6000
// ConnectTimeout: 6000
logging:
level:
# feign日志以什么级别监控哪个接口
com.cloud.openFeign.service.paymentFeign: debug
feign:
hystrix:
enabled: true
6.main:
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableHystrix
@EnableDiscoveryClient
public class mainhystrix80 {
public static void main(String[] args) {
SpringApplication.run(mainhystrix80.class,args);
}
}
7.客户端的在这里的controller层中做规范,1.5s没有收到数据就调用降级方法,注意服务降级的方法和调用的方法返回类型要一致。
@RequestMapping("/consumer/hystrixTimeOutTest")
@ResponseBody
@HystrixCommand(fallbackMethod = "timeoutHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
})
public ResultObject timeOut() throws InterruptedException {
return hystrixService.timeOut();
}
public ResultObject timeoutHandler() throws InterruptedException {
String s = "你访问的页面超时请稍后再试";
return ReturnResult.success(s);
}
}
8.service接口用feign
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface hystrixService {
@PostMapping("/timeOut")
@ResponseBody
public ResultObject timeOut() ;
}
9.测试

问题:
10上边的服务降级方法是一对一的,这样会引起代码膨胀,因此要配置一个全局的服务降级:
在controller类头上添加以下注解,在需要降级的方法上加一个@HystrixCommand标签,然后再配置一个对应的方法即可:
@DefaultProperties(defaultFallback = "fallBackDefaultMethod")
11.按照上述配置完成后发现还有一个问题,每个方法都要加@HystrixCommand注解,因为客户端调用服务端实际是在service的接口,用feign调用,因此做一个这个接口的实现类,进行
统一的服务降级处理,下边的那个方法是测试用的。

12.然后这个类怎么使用呢?把这个类放到service的@FeignClient注解中
@FeignClient(value = "CLOUD-PAYMENT-SERVICE",fallback = fallbackmethod.class)
13.当调用selectOne方法时,如果服务器宕机,会进入这个降级类对应的方法中,而在controller中,selectOne这个方法不用做任何的配置。

服务熔断:在失败一定次数以后会启动熔断机制(默认5秒调用20次失败),然后会慢慢恢复。与服务降级的区别是熔断会导致服务不可用,在不可用的那段时间即使调用的服务正确还是不行。
14.服务端service配置:在10s内有大于等于10次请求,且失败率达到百分之60之后断路器打开,默认5秒之后转为半开,尝试放过一次请求,如果请求通过那么断路器就会关闭。
@HystrixCommand(
fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),// 时间窗口期/时间范文
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")// 失败率达到多少后跳闸
}
)
public String paymentCircuitBreaker( Integer id) {
if (id < 0) {
throw new RuntimeException("*****id不能是负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
public String paymentCircuitBreaker_fallback( Integer id) {
return "id 不能负数,请稍后重试,o(╥﹏╥)o id:" + id;
}
15.hystrix图形化界面监控9001:
16.pom:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
17.主启动加上
@EnableHystrixDashboard
18.访问http://localhost:9001/hystrix

19.输入监控的端口,比如要监控的端口是80端口,就输入:http://localhost:80/hystrix.stream,delay:2000,title:T3
注意,在监控的服务的主启动类上加上一下代码,不然会报连接失败:
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
然后监控的服务要实现负载均衡,在这里我用的是openFeign,而且调用的接口要实现服务降级,也就是有@HystrixCommand注解,不然会一直loading....


浙公网安备 33010602011771号