两种实现方式
1.继承HystrixCommand 方式 ,重新getCacheKey方法
/**
* <h1>初始化 Hystrix 请求上下文环境</h1>
* */
@Slf4j
@Component
@WebFilter(
filterName = "HystrixRequestContextServletFilter",
urlPatterns = "/*",
asyncSupported = true
)
public class HystrixRequestContextServletFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// 初始化 Hystrix 请求上下文
// 在不同的 context 中缓存是不共享的
// 这个初始化是必须的
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
// 配置
hystrixConcurrencyStrategyConfig();
// 请求正常通过
chain.doFilter(request, response);
} finally {
// 关闭 Hystrix 请求上下文
context.shutdown();
}
}
/**
* <h2>配置 Hystrix 的并发策略</h2>
* */
public void hystrixConcurrencyStrategyConfig() {
try {
HystrixConcurrencyStrategy target =
HystrixConcurrencyStrategyDefault.getInstance();
HystrixConcurrencyStrategy strategy =
HystrixPlugins.getInstance().getConcurrencyStrategy();
if (strategy instanceof HystrixConcurrencyStrategyDefault) {
// 如果已经就是我们想要配置的
return;
}
// 将原来其他的配置保存下来
HystrixCommandExecutionHook commandExecutionHook =
HystrixPlugins.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier =
HystrixPlugins.getInstance().getEventNotifier();
HystrixMetricsPublisher metricsPublisher =
HystrixPlugins.getInstance().getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy =
HystrixPlugins.getInstance().getPropertiesStrategy();
// 先重置, 再把我们自定义的配置与原来的配置写回去
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(target);
HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
log.info("config hystrix concurrency strategy success");
} catch (Exception ex) {
log.error("Failed to register Hystrix Concurrency Strategy: [{}]",
ex.getMessage(), ex);
}
}
}
/**
* <h1>带有缓存功能的 Hystrix</h1>
* */
@Slf4j
public class CacheHystrixCommand extends HystrixCommand<List<ServiceInstance>> {
/** 需要保护的服务 */
private final NacosClientService nacosClientService;
/** 方法需要传递的参数 */
private final String serviceId;
private static final HystrixCommandKey CACHED_KEY =
HystrixCommandKey.Factory.asKey("CacheHystrixCommand");
public CacheHystrixCommand(NacosClientService nacosClientService, String serviceId) {
super(
HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey
.Factory.asKey("CacheHystrixCommandGroup"))
.andCommandKey(CACHED_KEY)
);
this.nacosClientService = nacosClientService;
this.serviceId = serviceId;
}
@Override
protected List<ServiceInstance> run() throws Exception {
log.info("CacheHystrixCommand In Hystrix Command to get service instance:" +
" [{}], [{}]", this.serviceId, Thread.currentThread().getName());
return this.nacosClientService.getNacosClientInfo(this.serviceId);
}
@Override
protected String getCacheKey() {
return serviceId;
}
@Override
protected List<ServiceInstance> getFallback() {
return Collections.emptyList();
}
/**
* <h2>根据缓存 key 清理在一次 Hystrix 请求上下文中的缓存</h2>
* */
public static void flushRequestCache(String serviceId) {
HystrixRequestCache.getInstance(
CACHED_KEY,
HystrixConcurrencyStrategyDefault.getInstance()
).clear(serviceId);
log.info("flush request cache in hystrix command: [{}], [{}]",
serviceId, Thread.currentThread().getName());
}
}@GetMapping("/cache-hystrix-command")
public void cacheHystrixCommand(@RequestParam String serviceId) {
// 使用缓存 Command, 发起两次请求
CacheHystrixCommand command1 = new CacheHystrixCommand(
nacosClientService, serviceId
);
CacheHystrixCommand command2 = new CacheHystrixCommand(
nacosClientService, serviceId
);
List<ServiceInstance> result01 = command1.execute();
List<ServiceInstance> result02 = command2.execute();
log.info("result01, result02: [{}], [{}]",
JSON.toJSONString(result01), JSON.toJSONString(result02));
// 清除缓存
CacheHystrixCommand.flushRequestCache(serviceId);
// 使用缓存 Command, 发起两次请求
CacheHystrixCommand command3 = new CacheHystrixCommand(
nacosClientService, serviceId
);
CacheHystrixCommand command4 = new CacheHystrixCommand(
nacosClientService, serviceId
);
List<ServiceInstance> result03 = command3.execute();
List<ServiceInstance> result04 = command4.execute();
log.info("result03, result04: [{}], [{}]",
JSON.toJSONString(result03), JSON.toJSONString(result04));
}2.注解
初始上下文Hystrix (配置并发策略)
/**
* <h1>使用注解方式开启 Hystrix 请求缓存</h1>
* */
@Slf4j
@Service
public class CacheHystrixCommandAnnotation {
private final NacosClientService nacosClientService;
public CacheHystrixCommandAnnotation(NacosClientService nacosClientService) {
this.nacosClientService = nacosClientService;
}
// 第一种 Hystrix Cache 注解的使用方法
@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
public List<ServiceInstance> useCacheByAnnotation01(String serviceId) {
log.info("use cache01 to get nacos client info: [{}]", serviceId);
return nacosClientService.getNacosClientInfo(serviceId);
}
@CacheRemove(commandKey = "CacheHystrixCommandAnnotation",
cacheKeyMethod = "getCacheKey")
@HystrixCommand
public void flushCacheByAnnotation01(String cacheId) {
log.info("flush hystrix cache key: [{}]", cacheId);
}
public String getCacheKey(String cacheId) {
return cacheId;
}
// 第二种 Hystrix Cache 注解的使用方法
@CacheResult
@HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
public List<ServiceInstance> useCacheByAnnotation02(@CacheKey String serviceId) {
log.info("use cache02 to get nacos client info: [{}]", serviceId);
return nacosClientService.getNacosClientInfo(serviceId);
}
@CacheRemove(commandKey = "CacheHystrixCommandAnnotation")
@HystrixCommand
public void flushCacheByAnnotation02(@CacheKey String cacheId) {
log.info("flush hystrix cache key: [{}]", cacheId);
}
// 第三种 Hystrix Cache 注解的使用方法
@CacheResult
@HystrixCommand(commandKey = "CacheHystrixCommandAnnotation")
public List<ServiceInstance> useCacheByAnnotation03(String serviceId) {
log.info("use cache03 to get nacos client info: [{}]", serviceId);
return nacosClientService.getNacosClientInfo(serviceId);
}
@CacheRemove(commandKey = "CacheHystrixCommandAnnotation")
@HystrixCommand
public void flushCacheByAnnotation03(String cacheId) {
log.info("flush hystrix cache key: [{}]", cacheId);
}
}@GetMapping("/cache-annotation-01")
public List<ServiceInstance> useCacheByAnnotation01(@RequestParam String serviceId) {
log.info("use cache by annotation01(controller) to get nacos client info: [{}]",
serviceId);
List<ServiceInstance> result01 =
cacheHystrixCommandAnnotation.useCacheByAnnotation01(serviceId);
List<ServiceInstance> result02 =
cacheHystrixCommandAnnotation.useCacheByAnnotation01(serviceId);
// 清除掉缓存
cacheHystrixCommandAnnotation.flushCacheByAnnotation01(serviceId);
List<ServiceInstance> result03 =
cacheHystrixCommandAnnotation.useCacheByAnnotation01(serviceId);
// 这里有第四次调用
return cacheHystrixCommandAnnotation.useCacheByAnnotation01(serviceId);
}