Hystrix几个概念
Hystrix 是什么:它是用于处理分布式系统的延时和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,例如超时、异常。Hystrix能够在保证一个依赖出现问题的情况下,不会导致整体服务失败,避免级联故障,以此来提高分布式系统的弹性。
断路器 本身是一种开关装置,当某个服务单元发生故障以后,通过断路器的故障监控,向调用方返回一个符合预期的、可处理的备选相应(fallback)而不是长时间的等待或者抛出调用方无法处理的异常,这样就保障了服务调用方的线程不会被长时间,不必要的占用,从而避免了在分布式系统中的蔓延,乃至雪崩。
服务降级(fallback)
服务器忙,请稍后再试,不让客户等待并立刻返回一个友好的提示
触发降级的情况:程序运行异常、超时、服务熔断触发降级、线程池/信号量打满也会导致服务降级。
务熔断(break)
类比保险丝达到最大服务访问以后,直接拒绝访问,然后调用服务降级的方法并返回友好提示
限流(flowlimit)
限制请求的流量,严禁一窝蜂的请求打过来。
创建模块服务提供者 cloud-provider-hystrix-payment8001
pom
<dependencies>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<!--Eureka 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.nyc.cloud</groupId>
<artifactId>cloud-api-commons</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-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
yml
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
#是否要将自己入驻到EurekaServer 默认为 true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true,单节点无所谓,集群必须设置ture才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka
instance:
instance-id: CloudProviderHystrixPayment8001
prefer-ip-address: true #显示ip
service
@Service
public class PaymentServiceImpl implements PaymentService {
@Override
public String paymentinfo_ok(Integer id) {
return "线程池 : " + Thread.currentThread().getName() + " paymentInfo_OK,id " + id;
}
@Override
@HystrixCommand(fallbackMethod = "paymentTimeOutFallBackMethod",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String paymentInfo_TimeOut(Integer id) {
int timeNumber = 1;
try {
TimeUnit.SECONDS.sleep(timeNumber);
}catch (InterruptedException e){
e.printStackTrace();
}
return "线程池 : " + Thread.currentThread().getName() + " paymentInfo_OK,id " + id + " 耗时 " + timeNumber;
}
public String paymentTimeOutFallBackMethod(Integer id){
return "线程池 : " + Thread.currentThread().getName() + " paymentInfo_TimeOut,id " + id + " 耗时 " + "/(ㄒoㄒ)/~~ 超时了......";
}
}
controller
@RestController
public class PaymentHystirxController {
@Autowired
private PaymentService paymentService;
@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_Ok(@PathVariable("id")Integer id){
return paymentService.paymentinfo_ok(id);
}
@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id")Integer id){
return paymentService.paymentInfo_TimeOut(id);
}
}
启动类
@EnableEurekaClient 注册进入Eureka
@EnableCircuitBreaker 开启降级注解。
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentHystrixMain8001.class);
}
}
降级
开启降级注解
创建服务消费方 cloud-consumer-feign-hystrix-order80
pom
<dependencies>
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<!--OpenFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<!--Eureka 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
yml
server:
port: 80
spring:
application:
name: consumer-feign-hystrix-order
eureka:
client:
register-with-eureka: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka
feign:
hystrix:
enabled: true
Service 远程调用
@Component
@FeignClient(value = "cloud-provider-hystrix-payment")
public interface PaymentHystrixService {
@GetMapping(value = "/payment/hystrix/ok/{id}")
String paymentInfo_OK(@PathVariable("id") Integer id);
@GetMapping(value = "/payment/hystrix/timeout/{id}")
String paymentInfo_TimeOut(@PathVariable("id")Integer id);
}
Controller
@RestController
@Slf4j
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping(value = "/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_OK(id);
return result;
}
@GetMapping(value = "/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallBackMethod",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
})
public String paymentInfo_TimeOut(@PathVariable("id")Integer id){
//TimeUnit.SECONDS.sleep(3);
String result = paymentHystrixService.paymentInfo_TimeOut(id);
return result;
}
public String paymentTimeOutFallBackMethod(@PathVariable("id")Integer id){
return "我是消费者80,对方支付系统繁忙请10秒钟以后在重试,呜呜呜";
}
}
启动类
@SpringBootApplication
@EnableEurekaClient //Eureka客户端
@EnableFeignClients //激活OpenFeign
@EnableHystrix
public class OrderConsumerMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderConsumerMain80.class);
}
}
全局服务降级@DefaultProperties
测试
Hystrix统配服务降级
服务熔断
服务达到最大访问以后,直接拒绝访问,然后调用服务降级方法返回友好提示。服务降级->服务熔断->恢复调用链路。
熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制,当扇出链路的某个微服务出错不可用或者响应时间太长,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误信息。当检测到该节点微服务调用响应正常后,回复调用链路
在spring cloud中,熔断机制通过Hystrix实现,Hystrix会监控微服务间的调用状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败,就会启动熔断机制,熔断机制的注解是 @HystrixCommand
服务熔断演示
@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(@PathVariable("id")Integer id){
if (id<0){
throw new RuntimeException("*********id,不能负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id")Integer id){
return "id 不能为负数,请稍后重试,┭┮﹏┭┮,id:" + id;
}
@GetMapping(value = "/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id")Integer id){
String result = paymentService.paymentCircuitBreaker(id);
log.info("********result:"+result);
return result;
}
Hystrix图形化
搭建图形化界面
pom
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.1.RELEASE</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.nyc.cloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
yml
server:
port: 9001
启动类
@SpringBootApplication
@EnableHystrixDashboard //开启面板
public class HystrixDashBordMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashBordMain9001.class);
}
}