我是靠谱客的博主 标致黑米,这篇文章主要介绍Hystrix框架5--请求缓存和collapser,现在分享给大家,希望可以做个参考。

简介

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

缓存

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

应用

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

复制代码
1
2
3
4
5
@Override protected String getCacheKey() { return String.valueOf(value); }

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

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

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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中需要将原先的缓存失效

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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可以合并多个请求一起调用

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//需要定义一个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是不支持跨线程。

转载于:https://www.cnblogs.com/resentment/p/5914390.html

最后

以上就是标致黑米最近收集整理的关于Hystrix框架5--请求缓存和collapser的全部内容,更多相关Hystrix框架5--请求缓存和collapser内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(87)

评论列表共有 0 条评论

立即
投稿
返回
顶部