简介

在Hystrix中有个Request的概念,有一些操作需要在request中进行

缓存

在Hystrix调用服务时,如果只是查询接口,可以使用缓存进行优化,从而跳过真实访问请求。

应用

需要启用缓存的话需要重写command中getCacheKey方法

    @Override
protected String getCacheKey() {
return String.valueOf(value);
}

之后就可以调用了

但是如果直接调用command的运行相关方法会得到以下错误

Caused by: java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?

这里说需要初始化HystrixRequestContext,在Hystrix中带缓存的command是必须在request中调用的。

public void testWithCacheHits() {
//初始化context
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
//两个一样的command
CommandUsingRequestCache command2a = new CommandUsingRequestCache(2);
CommandUsingRequestCache command2b = new CommandUsingRequestCache(2); assertTrue(command2a.execute());
// 第一次调用的返回是否从cache获得是false
assertFalse(command2a.isResponseFromCache()); assertTrue(command2b.execute());
// 第而次调用的返回是否从cache获得是true
assertTrue(command2b.isResponseFromCache());
} finally {
//关闭context
context.shutdown();
}
}

在不同context中的缓存是不共享的,还有这个request内部一个ThreadLocal,所以request只能限于当前线程

更新缓存

如果服务同时有更新的操作,那么在request中需要将原先的缓存失效

public static class GetterCommand extends HystrixCommand<String> {
//getter key 用于命名当前command,之后清楚缓存时需要
private static final HystrixCommandKey GETTER_KEY = HystrixCommandKey.Factory.asKey("GetterCommand");
private final int id; public GetterCommand(int id) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GetSetGet"))
.andCommandKey(GETTER_KEY));
this.id = id;
} @Override
protected String run() {
return prefixStoredOnRemoteDataStore + id;
} @Override
protected String getCacheKey() {
return String.valueOf(id);
} /**
* Allow the cache to be flushed for this object.
*/
public static void flushCache(int id) {
//这里从HystrixRequestCache的getInstance静态方法中找到对应实例,并将响应值清除
HystrixRequestCache.getInstance(GETTER_KEY,
HystrixConcurrencyStrategyDefault.getInstance()).clear(String.valueOf(id));
}
}

Collapser

Collapser可以合并多个请求一起调用

//需要定义一个Collapser
public class CommandCollapserGetValueForKey extends HystrixCollapser<List<String>, String, Integer> { private final Integer key; public CommandCollapserGetValueForKey(Integer key) {
this.key = key;
} @Override
public Integer getRequestArgument() {
return key;
} @Override
protected HystrixCommand<List<String>> createCommand(final Collection<CollapsedRequest<String, Integer>> requests) {
return new BatchCommand(requests);
} @Override
protected void mapResponseToRequests(List<String> batchResponse, Collection<CollapsedRequest<String, Integer>> requests) {
int count = 0;
for (CollapsedRequest<String, Integer> request : requests) {
request.setResponse(batchResponse.get(count++));
}
}
//底层command实现
private static final class BatchCommand extends HystrixCommand<List<String>> {
private final Collection<CollapsedRequest<String, Integer>> requests; private BatchCommand(Collection<CollapsedRequest<String, Integer>> requests) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
.andCommandKey(HystrixCommandKey.Factory.asKey("GetValueForKey")));
this.requests = requests;
}
//内部还是遍历入参进行调用
@Override
protected List<String> run() {
ArrayList<String> response = new ArrayList<String>();
for (CollapsedRequest<String, Integer> request : requests) {
// artificial response for each argument received in the batch
response.add("ValueForKey: " + request.getArgument());
}
return response;
}
}
} @Test
public void testCollapser() throws Exception {
//初始化request
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
//直接调用collapser
Future<String> f1 = new CommandCollapserGetValueForKey(1).queue();
Future<String> f2 = new CommandCollapserGetValueForKey(2).queue();
Future<String> f3 = new CommandCollapserGetValueForKey(3).queue();
Future<String> f4 = new CommandCollapserGetValueForKey(4).queue(); assertEquals("ValueForKey: 1", f1.get());
assertEquals("ValueForKey: 2", f2.get());
assertEquals("ValueForKey: 3", f3.get());
assertEquals("ValueForKey: 4", f4.get());
//只调用了一次command
// assert that the batch command 'GetValueForKey' was in fact
// executed and that it executed only once
assertEquals(1, HystrixRequestLog.getCurrentRequest().getExecutedCommands().size());
HystrixCommand<?> command = HystrixRequestLog.getCurrentRequest().getExecutedCommands().toArray(new HystrixCommand<?>[1])[0];
// assert the command is the one we're expecting
assertEquals("GetValueForKey", command.getCommandKey().name());
// confirm that it was a COLLAPSED command execution
assertTrue(command.getExecutionEvents().contains(HystrixEventType.COLLAPSED));
// and that it was successful
assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));
} finally {
//关闭request
context.shutdown();
}
}

Collapser可以用来一起调用一批请求,在第一个调用get时会对积压的command一起调用。

总结

Hystrix的Request主要就是cache和collapser用到。在一般web应用中可以在filter中加入context的初始化和关闭逻辑。还要注意request是不支持跨线程。

Hystrix框架5--请求缓存和collapser的更多相关文章

  1. SpringCloud实战-Hystrix线程隔离&请求缓存&请求合并

    接着上一篇的Hystrix进行进一步了解. 当系统用户不断增长时,每个微服务需要承受的并发压力也越来越大,在分布式环境中,通常压力来自对依赖服务的调用,因为亲戚依赖服务的资源需要通过通信来实现,这样的 ...

  2. SpringCloud实战4-Hystrix线程隔离&请求缓存&请求合并

    接着上一篇的Hystrix进行进一步了解. 当系统用户不断增长时,每个微服务需要承受的并发压力也越来越大,在分布式环境中,通常压力来自对依赖服务的调用,因为亲戚依赖服务的资源需要通过通信来实现,这样的 ...

  3. 第六十二篇、AFN3.0封装网络请求框架,支持缓存

    1.网络请求 第一种实现方式: 功能:GET POST 请求 缓存逻辑: 1.是否要刷新本地缓存,不需要就直接发起无缓存的网络请求,否则直接读取本地数据 2.需要刷新本地缓存,先读取本地数据,有就返回 ...

  4. Spring-cloud (八) Hystrix 请求缓存的使用

    前言: 最近忙着微服务项目的开发,脱更了半个月多,今天项目的初版已经完成,所以打算继续我们的微服务学习,由于Hystrix这一块东西好多,只好多拆分几篇文章写,对于一般对性能要求不是很高的项目中,可以 ...

  5. hystrix中request cache请求缓存

    有一个概念,叫做reqeust context,请求上下文,一般来说,在一个web应用中, 我们会在一个filter里面,对每一个请求都施加一个请求上下文,就是说,tomcat容器内,每一次请求,就是 ...

  6. Android Xutils框架HttpUtil Get请求缓存问题

    话说,今天和服务器开发人员小小的逗逼了一下,为啥呢? 话说今天有个"收藏产品"的请求接口,是get request的哦,我客户端写好接口后,点击"收藏按钮",返 ...

  7. hystrix源码之请求缓存

    HystrixRequestCache 请求缓存.内部是一个静态ConcurrentHashMap存储各个命令的缓存器,RequestCacheKey为key,HystrixRequestCache为 ...

  8. Hystrix-request cache(请求缓存)

    开启请求缓存 请求缓存在run()和construce()执行之前生效,所以可以有效减少不必要的线程开销.你可以通过实现getCachekey()方法来开启请求缓存. package org.hope ...

  9. Spring Cloud(Dalston.SR5)--Hystrix 断路器-合并请求

    在 Spring Cloud 中可以使用注解的方式来支持 Hystrix 的合并请求,缓存与合并请求功能需要先初始化请求上下文才能实现,因此,必须实现 javax.servlet.Filter 用于创 ...

随机推荐

  1. 金融计算器app的下载情况

    下图就是一个多月来的下载量情况~话不多说,直接上图哈. 数据来源:百度开发者平台

  2. 配置apue的头文件apue.h和unp的头文件anp.h

    配置apue的头文件apue.h和unp的头文件anp.h 如果要使用gcc -g 来生成可调试文件一定要修改Make.defines.linux文件中的CFLAGS变量 修改为:CFLAGS=-an ...

  3. Linux学习笔记(13)-进程通信|命名管道

    匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢? 别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道-- 所谓命名 ...

  4. windows下node环境配置

    1.在node官网上下载合适版本的node安装包,官网地址:http://nodejs.org/#download:我下载的6.5最新版本: 2.安装node,都是系统默认的,一直安装下去: 3.在c ...

  5. c程序对于文件的处理

    C 文件读写 上一章我们讲解了 C 语言处理的标准输入和输出设备.本章我们将介绍 C 程序员如何创建.打开.关闭文本文件或二进制文件. 一个文件,无论它是文本文件还是二进制文件,都是代表了一系列的字节 ...

  6. java spring 配置文件的读取

    java读取本地配置文件主要分为两类,一类为class相关文件或子文件夹下,一类文件 为jar包外配置文件. class相关文件夹或子文件夹下读取配置文件可以使用Object.class.getRes ...

  7. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

  8. 主成分分析 (PCA) 与其高维度下python实现(简单人脸识别)

    Introduction 主成分分析(Principal Components Analysis)是一种对特征进行降维的方法.由于观测指标间存在相关性,将导致信息的重叠与低效,我们倾向于用少量的.尽可 ...

  9. 洛谷1640 bzoj1854游戏 匈牙利就是又短又快

    bzoj炸了,靠离线版题目做了两道(过过样例什么的还是轻松的)但是交不了,正巧洛谷有个"大牛分站",就转回洛谷做题了 水题先行,一道傻逼匈牙利 其实本来的思路是搜索然后发现写出来类 ...

  10. sass和compass的配置

    http://note.youdao.com/share/?id=4f57187f9695bcaadf80516187d2de0e&type=note 当执行安装sass出错时,可以试试这个命 ...