hystrix-client8011
hystrix-feign-client80
创建hystrix-client8011
:(SpringBoot项目的创建这里不做介绍)
更改POM文件
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
添加application.yml
server:
port: 8011 #端口号
spring:
application:
name: hystrix-client-service #服务名称
eureka:
client:
serviceUrl:
defaultZone: http://eurekaServer8761.com:8761/eureka/,http://eurekaServer8762.com:8762/eureka/ #eurekaServer集群地址
instance:
instance-id: service8011
prefer-ip-address: true
添加主启动类
/**
* 主启动类
* @EnableEurekaClient:开启Eureka客户端组件
* @EnableCircuitBreaker:开启Hystrix组件
*/
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class HystrixClientMain8011 {
public static void main(String[] args) {
SpringApplication.run(HystrixClientMain8011.class,args);
}
}
提供接口及实现类
public interface UserServiceInter {
String success(String userId);
String timeOut(String userId);
}
@Service
public class UserServiceInterImpl implements UserServiceInter {
@Override
public String success(String userId) {
return "执行成功!";
}
/**
* @HystrixCommand:对接口进行降级的注解
* fallbackMethod:指定降级方法
* commandProperties:用于配置降级属性,多个属性用逗号分隔
* @HystrixProperty:降级属性的注解
* name:属性名称,这里以超时为例
* value:最大超时时间,执行时间大于等于它时直接降级
*/
@HystrixCommand(fallbackMethod = "fallbackTimeOut",
commandProperties = {
@HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",
value = "2000")
})
@Override
public String timeOut(String userId) {
try {
TimeUnit.MILLISECONDS.sleep(3000);
return "执行成功,耗时三秒钟!";
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
*降级方法
*/
public String fallbackTimeOut(String userId){
return "hystrix-client8011:服务器忙请稍后再试!userId="+userId;
}
}
编写Controller
@RestController
@Slf4j
public class TestController {
@Value("${server.port}")
private String port;
@Autowired
private UserServiceInter userServiceInter;
@GetMapping(value = "service/success/{userId}")
public String success(@PathVariable("userId") String userId){
return userServiceInter.success(userId);
}
@GetMapping(value = "service/timeOut/{userId}")
public String timeOut(@PathVariable("userId") String userId){
return userServiceInter.timeOut(userId);
}
}
创建hystrix-feign-client80
:(SpringBoot项目的创建这里不做介绍)
更改POM文件
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
dependencies>
添加application.yml
server:
port: 80 #端口号
spring:
application:
name: hystrix-feign-client-consumption #服务名称(消费者)
eureka:
client:
serviceUrl:
defaultZone: http://eurekaServer8761.com:8761/eureka/,http://eurekaServer8762.com:8762/eureka/
ribbon:
ReadTimeout: 5000 #建立连接所用的时间,指的是两端连接的时间设置5秒钟
ConnectTimeout: 5000 #建立连接后从服务器读取到资源所用的时间设置5秒钟
feign:
hystrix:
enabled: true #开启hystrix的支持
logging:
level:
com.dwj.springcloud.service.UserServiceInter: debug #feign日志以debug级别监控与服务提供者绑定的接口
添加主启动类
/**
* @EnableFeignClients:开启OpenFeign
* @EnableHystrix:开启Hystrix组件
*/
@SpringBootApplication
@EnableFeignClients
@EnableHystrix
public class HystrixFeignClientMain80 {
public static void main(String[] args) {
SpringApplication.run(HystrixFeignClientMain80.class,args);
}
}
新建接口,使用OpenFeign完成对服务提供者的接口绑定,可参考OpenFeign基本介绍
@Component
@FeignClient(value = "HYSTRIX-CLIENT-SERVICE")
public interface UserServiceInter {
@GetMapping(value = "service/success/{userId}")
String success(@PathVariable("userId") String userId);
@GetMapping(value = "service/timeOut/{userId}")
String timeOut(@PathVariable("userId") String userId);
}
编写Controller
@RestController
@Slf4j
public class TestController {
@Value("${server.port}")
private String port;
@Autowired
private UserServiceInter userServiceInter;
@GetMapping(value = "consumption/success/{userId}")
public String success(@PathVariable("userId") String userId){
return userServiceInter.success(userId);
}
/**
*设置最大超时时间为一秒钟,当服务接口响应时间大于等于一秒钟时直接降级
*/
@HystrixCommand(fallbackMethod = "timeOutFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "1000")
})
@GetMapping(value = "consumption/timeOut/{userId}")
public String timeOut(@PathVariable("userId") String userId){
return userServiceInter.timeOut(userId);
}
/**
*降级方法
*/
public String timeOutFallback(@PathVariable("userId") String userId){
return "hystrix-feign-client80:客户端繁忙请稍后再试userId="+userId;
}
}
修改服务提供者hystrix-client8011
的降级时间,最大超时时间为五秒钟,方法执行时间为三秒钟所以该服务接口正常
/**
* @HystrixCommand:对接口进行降级的注解
* fallbackMethod:指定降级方法
* commandProperties:用于配置降级属性,多个属性用逗号分隔
* @HystrixProperty:降级属性的注解
* name:属性名称,这里以超时为例
* value:最大超时时间,执行时间大于等于它时直接降级
*/
@HystrixCommand(fallbackMethod = "fallbackTimeOut",
commandProperties = {
@HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",
value = "5000")
})
@Override
public String timeOut(String userId) {
try {
TimeUnit.MILLISECONDS.sleep(3000);
return "执行成功,耗时三秒钟!";
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
访问:http://127.0.0.1/consumption/timeOut/1234
,服务提供者接口正常,但调用者客户端自己最大超时时间是一秒钟,所以直接降级
注意:在实际服务调用中,一般都是调用者客户端进行降级,很少出现客户端和服务端都降级的情况这里只做演示
上面虽然实现了服务降级,但是如果一个类中有多个方法都需要超时降级,那岂不是要在每个方法头上写@HystrixCommand降级配置
解决方案:@DefaultProperties
/**
* @DefaultProperties:针对本类的全局降级注解
* defaultFallback:默认全局降级方法
*/
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "defaultFallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "1000")
})
public class TestController {
@Value("${server.port}")
private String port;
@Autowired
private UserServiceInter userServiceInter;
@GetMapping(value = "consumption/success/{userId}")
public String success(@PathVariable("userId") String userId){
return userServiceInter.success(userId);
}
@HystrixCommand
@GetMapping(value = "consumption/timeOut/{userId}")
public String timeOut(@PathVariable("userId") String userId){
return userServiceInter.timeOut(userId);
}
/**
*降级方法
*/
public String defaultFallback(){
return "hystrix-feign-client80:客户端繁忙请稍后再试";
}
}
全局降级以后一个类只需要配置一次降级属性,如果需要针对某个方法进行自定义降级处理,再单独定义即可
强调一点:上面虽然配置的是对超时进行降级,但是如果程序出现运行时异常、服务宕机也一样会走降级的方法
虽然全局服务降级可以节省部分代码量,但是降级的逻辑和我们的业务代码耦合度太高
解决方法:在OpenFeign的接口绑定上增加fallback属性
/**
* fallback:降级类的字节码文件,该类实现了本接口,故完成对每个接口方法的降级
*/
@Component
@FeignClient(value = "HYSTRIX-CLIENT-SERVICE",fallback = UserServiceFallback.class)
public interface UserServiceInter {
@GetMapping(value = "service/success/{userId}")
String success(@PathVariable("userId") String userId);
@GetMapping(value = "service/timeOut/{userId}")
String timeOut(@PathVariable("userId") String userId);
}
@Component
public class UserServiceFallback implements UserServiceInter {
@Override
public String success(String userId) {
return "hystrix-feign-client80:客户端繁忙请稍后再试,success方法";
}
@Override
public String timeOut(String userId) {
return "hystrix-feign-client80:客户端繁忙请稍后再试,timeOut方法";
}
}
客户端Controller代码恢复
@RestController
@Slf4j
public class TestController {
@Value("${server.port}")
private String port;
@Autowired
private UserServiceInter userServiceInter;
@GetMapping(value = "consumption/success/{userId}")
public String success(@PathVariable("userId") String userId){
return userServiceInter.success(userId);
}
@GetMapping(value = "consumption/timeOut/{userId}")
public String timeOut(@PathVariable("userId") String userId){
return userServiceInter.timeOut(userId);
}
}
修改hystrix-client8011
的接口实现类
@Service
public class UserServiceInterImpl implements UserServiceInter {
@Override
public String success(String userId) {
/**
* 模拟一个运行时异常
*/
int i = 10/0;
return "执行成功!";
}
访问:http://127.0.0.1/consumption/success/123
,客户端直接降级
本文只是Hystrix服务降级简单入门,如有错误请各位读者及时提出。以上案列均参考尚硅谷周阳老师B站视频