Request Cache 减压
- Request Cache 相对与降级来说,更像是一种减压手段
- 使用 @CacheResult 缓存返回值
- Request Cache 不生效?
1. 新建 hystrix-consumer2 用于 Request Cache 的 demo测试
2. 新建 RequestCacheService 类,调用 Feign 接口,方法上配置 @CacheResult 、 @HystrixCommand @commandKey 注解
代码展现从 Controller → RequestCacheService → interface(Feign) → application.properties
Controller :
@RestController
public class ConsumerController {
@Autowired
RequestCacheService requestCacheService;
/**
* 测试 hystrix的 Request Cache
* @param name
* @return
* @throws InterruptedException
*/
@GetMapping("/hc/{name}")
public User hc(@PathVariable("name") String name) throws InterruptedException {
// 在同一个上下文中,requestCache 只被调用一次。
// 这个context 打开,那么也就需要关闭,一般使用 try{}finally 来关闭。
// @Cleanup 是 lombok 中的注解,默认是close方法。如果关闭方法不是close。而是shutdown. 那就这样写 @Cleanup("shutdown")
@Cleanup HystrixRequestContext context = HystrixRequestContext.initializeContext();
System.err.println( "------[hc] name : "+name );
// 如果像这样,调用多次,但是name 没有改变,会把结果缓存。只会调用一次请求
User user = requestCacheService.requestCache(name);
user = requestCacheService.requestCache(name);
return user;
// try{}finally{ 关闭上下文
// context.close();;
// }
}
}
【思考】 扩大上下文的作用范围 ,缓存的作用也会扩大。 只要在一个 context 上下文中,就会直接去拿缓存结果。
RequestCacheService :
@CacheResult 缓存结果 requestCache() 方法返回的结果会加到缓存里
@CacheKey 缓存结果的key 是哪个 。这里是 name
@HystrixCommand(commandKey = "11223") 11223在配置文件properties中已配置。
@Service
public class RequestCacheService {
@Autowired
HystrixProducerService service;
@CacheResult
@HystrixCommand(commandKey = "11223") // 设定方法超时时间
public User requestCache(@CacheKey String name){
System.err.println("requestCache name: "+name);
User user = new User();
user.setName(name);
user = service.hystrixcommand(user);
System.err.println("after... requestCache name: "+name);
return user;
}
}
Feign 接口
@FeignClient(value = "eureka-client",fallback = Fallback.class)
public interface HystrixProducerService {
@PostMapping("/hc")
public User hystrixcommand(@RequestBody User user);
}
服务提供者:
@RestController
@Slf4j
public class ProviderController {
/**
* 用于 Hystrix 的 requestCache 测试
* @param user
* @return
*/
@PostMapping("/hc")
public User requestCache(@RequestBody User user){
user.setName("提供者");
user.setAddress(port);
System.err.println("----- [hc] port: "+port);
return user;
}
}
properties:
server.port=9880
spring.application.name=hystrix-consumer
eureka.client.serviceUrl.defaultZone=http://eureka1:8860/eureka
## 是否需要引入IP。 就是这个 服务注册到 eureka 注册中心后,而显示 这个ip
eureka.instance.prefer-ip-address=true
## 这里可以写个表达式 .这两行意思就是注册到注册中心后显示 自己的ip地址
eureka.instance.instance-id=${spring.application.name}: ${eureka.instance.ip-address}:${server.port}
# 允许bean定义上的重载
spring.main.allow-bean-definition-overriding=true
# ---------------------- Feign & Hystrix 配置--------------------------
# 开启 Feign 下面的 hystrix 功能
feign.hystrix.enabled=true
# 是否开启服务降级(默认开启)
hystrix.command.default.fallback.enabled=true
# Hystrix 全局超时
hystrix.command.default.execution.timeout.enable=true
# 超时时间 2 秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
# 超时以后终止线程
hystrix.command.default.execution.isolation.thread.interruptOnTimeout=true
# 取消的时候终止线程
hystrix.command.default.execution.isolation.thread.interruptOnFutureCancel=true
# 单独设置某个方法的超时时间,覆盖全局超时时间
hystrix.command.HystrixProducerService#hystrixTimeOut(int).execution.isolation.thread.timeoutInMilliseconds=3000
# 单独设置一个 commandKey 超时时间。 代码中方法可直接使用这个 key 的超时时间
hystrix.command.11223.execution.isolation.thread.timeoutInMilliseconds=3000
# requestCache相关功能配置 开启访问缓存功能(默认开启)
hystrix.command.default.requestCache.enabled=true
#【注意:eureka-client 是服务名。 在这里作为服务提供者,被调用】
# 每台机器最大重试次数。 第一次连过去,失败,还能重试两次。相当于总共连接3次
eureka-client.ribbon.MaxAutoRetries=0
# 可以再重试几台机器。
eureka-client.ribbon.MaxAutoRetriesNextServer=0
# 连接超时; 1.建立连接
eureka-client.ribbon.ConnectTimeout=8000
# 业务处理超时 2.业务处理
eureka-client.ribbon.ReadTimeout=9000
# 在 所有 Http Method 进行重试。 默认是 false. 【谨慎开启】 ,否则 delete , update , insert 操作需要做幂等
eureka-client.ribbon.OkToRetryOnAllOperations=true
Hystrix Fallback 多级降级
服务消费者 调用 服务提供方 的api接口,降级方案中报错,再次降级
@RestController
public class ConsumerController {
@Autowired
HystrixProducerService service;
/**
* hystrix的 多级降级方案
*/
@GetMapping("/fb/{time}")
public String fallback(@PathVariable("time") int time){
// 调用服务提供者的 Api 接口
service.hystrixFallback(time);
return "hystrixFallback success !";
}
}
service 中方法
@FeignClient(value = "eureka-client",fallback = Fallback.class)
public interface HystrixProducerService {
/**
* 用于测试 hystrix 多级降级方案 。 降级方法报错,继续降级
* @param time
* @return
*/
@GetMapping("/hystrix/{time}")
public String hystrixFallback(@PathVariable("time") int time);
}
多降级方案
@Component
public class Fallback implements HystrixProducerService {
@Override
@HystrixCommand(fallbackMethod = "hystrixFallback1")
public String hystrixFallback(int time){
System.err.println("fallback 降级策略 1");
// 业务处理,抛出异常
throw new RuntimeException(" 第一次降级处理 ....");
}
public String hystrixFallback1(int time){
System.err.println("fallback 降级策略 2");
return " 多级降级处理 Success ";
}
CommandKey 与 CommandProperties 属性相互结合自定义超时时间
单独设置某个服务的http调用断路器超时时间。
这里针对于某个特定的方法,自定义超时时间。
这个是 断路器 整体超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000。
@HystrixProperty 可以配置多个
@HystrixCommand(
fallbackMethod = "fallbackhello4timeout",
commandKey = "helloKey",
commandProperties = {
@HystrixProperty(name="execution.timeout.enabled",value="true"), // 自定义的,开启超时
@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000") // 自定义的,超时时间1000毫秒
}
)
public String hello4timeout() {
// 调用服务提供者的 Api 接口; 【注意这一步,service.hystrixFallback(time) 调用fegin调用本身也会有超时时间的】
String ret = service.hystrixFallback(time);
System.out.println(" consumer1 hello4timeout ......................");
return ret;
}
// 注意这个调用失败的方法名一定要一致
public String fallbackhello4timeout() {
System.out.println(" /// hello4timeout ......................");
return "hello4timeout 服务调用失败,进行降级处理!进入降级策略方法";
}