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....

 

 



 

 

 

 


posted @ 2020-05-12 17:36  ~笑春风~  阅读(416)  评论(0)    收藏  举报