Hystrix是一个用于处理分布式系统的延迟和容错的开源库,它能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性。
在分布式系统中,服务与服务之间的调用难免会发生调用失败、超时、异常等情况;为了解决这些问题,可以用到Hystrix的服务降级。
在前面OpenFeign调服务的基础上,我们可以新增一个模块来进行服务降级的测试
首先编写pom 文件
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--引入自己定义的通用api包-->
<dependency>
<groupId>com.cq.better</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-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--mybatisplus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.5.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
yml文件
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/xxx?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: xxx
password: xxx
eureka:
client:
#false表示不向服务端注册自己
register-with-eureka: true
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: true
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #集群版
instance:
instance-id: PaymentHystrix8001
prefer-ip-address: true #访问路径可以显示IP地址
主启动类PaymentHystrixMain8001
(主启动类要加上注解@EnableCircuitBreaker)
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class PaymentHystrixMain8001
{
public static void main(String[] args)
{
SpringApplication.run(PaymentHystrixMain8001.class,args);
}
}
service接口和实现类
public interface PaymentService
{
public String paymentInfo_ok(Integer id);
public String paymentInfo_TimeOut(Integer id);
}
在impl实现类的paymentInfo_TimeOut方法中,设置睡眠5秒钟;
在头上加上注解:
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") })
"fallbackMethod":服务调用失败时,调用paymentInfo_TimeOutHandler方法;;
"execution.isolation.thread.timeoutInMilliseconds",value = "3000":时间为3秒,超过3秒就执行
paymentInfo_TimeOutHandler方法。
(因为睡眠时间为5秒,而注解设置的时间为3秒,所以3秒后睡眠时间还没结束,服务未通,就会执行paymentInfo_TimeOutHandler)
@Service
public class PaymentServiceImpl implements PaymentService
{
@Override
public String paymentInfo_ok(Integer id)
{
return "线程池:"+Thread.currentThread().getName()+" paymentInfo_ok,id: "+id+"\t"+"O(∩_∩)O哈哈~";
}
@Override
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
public String paymentInfo_TimeOut(Integer id)
{
int timeNumber = 5;
try
{
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e)
{
e.printStackTrace();
}
return "线程池:"+Thread.currentThread().getName()+" paymentInfo_TimeOut,id: "+id+"\t"+"O(∩_∩)O哈哈~"+"耗时(秒)"+timeNumber;
}
public String paymentInfo_TimeOutHandler(Integer id)
{
return "线程池:"+Thread.currentThread().getName()+" 系统繁忙或运行报错,请稍后再试...,id: "+id+"\t"+"/(ㄒoㄒ)/~~";
}
}
controller类
@RestController
@Slf4j
public class PaymentController
{
@Resource
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping(value = "/payment/hystrix/ok/{id}")
public String paymentInfo_ok(@PathVariable("id") Integer id)
{
String result = paymentService.paymentInfo_ok(id);
log.info("--->result:"+result);
return result;
}
@GetMapping(value = "/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
{
String result = paymentService.paymentInfo_TimeOut(id);
log.info("--->result:"+result);
return result;
}
}
启动服务后进行测试 localhost:8001/payment/hystrix/timeout/1
会发现服务降级成功