java 上下文缓存_教程:一起学习Hystrix--Hystrix请求处理

本文详细介绍了Hystrix中的请求缓存和请求合并机制。通过实现`getCacheKey()`启用请求缓存,利用`HystrixRequestContext`进行上下文管理。同时,展示了如何使用HystrixCollapser进行请求合并,减少下游依赖的调用次数。此外,还讨论了请求上下文的设置方法,包括在Servlet Filter中的应用。
摘要由CSDN通过智能技术生成

目录

Hystrix本系列博文

请求缓存

请求合并

请求上下文设置

声明

Hystrix本系列博文

以下为博主写Hystrix系列的文章列表

点击查看 Hystrix入门

点击查看 Hystrix命令执行

点击查看 Hystrix处理异常机制(降级方法)

点击查看 Hystrix命令名称、分组、线程池

请求缓存

您可以通过在 HystrixCommand 或 HystrixObservableCommand 上实现 getCacheKey() 方法来启用请求缓存,如下所示:

public class CommandHelloRequestCache extends HystrixCommand {

private final int value;

protected CommandHelloRequestCache(int value) {

super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));

this.value = value;

}

@Override

protected Boolean run() {

return value == 0 || value % 2 == 0;

}

@Override

protected String getCacheKey() {

return String.valueOf(value);

}

}

点击查看 完整源码(含单元测试)

在一个简单单元测试中使用,如下:

@Test

public void testWithoutCacheHits() {

HystrixRequestContext context = HystrixRequestContext.initializeContext();

try {

assertTrue(new CommandHelloRequestCache(2).execute());

assertFalse(new CommandHelloRequestCache(1).execute());

assertTrue(new CommandHelloRequestCache(0).execute());

assertTrue(new CommandHelloRequestCache(58672).execute());

} finally {

context.shutdown();

}

}

通常,请求上下文将被初始化,并通过封装用户请求或其他生命周期钩子的ServletFilter关闭。

下面示例,展示了在请求上下文中,命令如何从缓存检索它们的值(以及如何查询一个对象确定它的值是否来自缓存 ):

@Test

public void testWithCacheHits() {

HystrixRequestContext context = HystrixRequestContext.initializeContext();

try {

CommandHelloRequestCache command2a = new CommandHelloRequestCache(2);

CommandHelloRequestCache command2b = new CommandHelloRequestCache(2);

assertTrue(command2a.execute());

// 第一次执行这个命令时不是从缓存返回的值

assertFalse(command2a.isResponseFromCache());

assertTrue(command2b.execute());

// 第二次执行这个命令时是从缓存返回的值

assertTrue(command2b.isResponseFromCache());

} finally {

context.shutdown();

}

// 开启一个新的请求上下文

context = HystrixRequestContext.initializeContext();

try {

CommandHelloRequestCache command3b = new CommandHelloRequestCache(2);

assertTrue(command3b.execute());

// 这个新请求执行这个命令也不会从缓存返回值

assertFalse(command3b.isResponseFromCache());

} finally {

context.shutdown();

}

}

请求合并

请求合并者使多个请求在单个HystrixCommand实例被批量执行。自批处理创建后,合并者可以使用批次大小和运行时间作为执行批次处理的触发器。

Hystrix 支持的请求合并有两种:请求范围和全局范围。这个可以在合并器构造函数中配置,默认情况下是请求范围。

请求范围的合并器收集每个 HystrixRequestContext的批处理,而全局范围的合并器则会在多个 HystrixRequestContext中收集一批批处理。 因此,如果下游依赖项不能在单个命令调用中处理多个 HystrixRequestContext,那么请求作用域合并者做出了恰当的选择。

在Netflix(Hystrix开源者),只使用请求作用域的合并器,因为所有当前的系统都是建立在每个命令使用单个HystrixRequestContext的假设之上。 由于一批次仅为每个请求,在同一请求命令使用不同参数并行执行时,合并是有效的。

下面是一个简单的例子,说明如何实现一个请求范围的 HystrixCollapser:

public class CommandHelloCollapser extends HystrixCollapser, String, Integer> {

private final Integer key;

public CommandHelloCollapser(Integer key) {

this.key = key;

}

@Override

public Integer getRequestArgument() {

return key;

}

@Override

protected HystrixCommand> createCommand(final Collection> requests) {

return new BatchCommand(requests);

}

@Override

protected void mapResponseToRequests(List batchResponse, Collection> requests) {

int count = 0;

for (CollapsedRequest request : requests) {

request.setResponse(batchResponse.get(count++));

}

}

private static final class BatchCommand extends HystrixCommand> {

private final Collection> requests;

private BatchCommand(Collection> requests) {

super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))

.andCommandKey(HystrixCommandKey.Factory.asKey("GetValueForKey")));

this.requests = requests;

}

@Override

protected List run() {

ArrayList response = new ArrayList();

for (CollapsedRequest request : requests) {

// artificial response for each argument received in the batch

response.add("ValueForKey: " + request.getArgument());

}

return response;

}

}

}

点击查看 完整源码以及单元测试

下面的单元测试展示了如何使用一个合并器自动将 CommandHelloCollapser 的4个执行在一个 HystrixCommand 中执行:

@Test

public void testCollapser() throws Exception {

HystrixRequestContext context = HystrixRequestContext.initializeContext();

try {

Future f1 = new CommandHelloCollapser(1).queue();

Future f2 = new CommandHelloCollapser(2).queue();

Future f3 = new CommandHelloCollapser(3).queue();

Future f4 = new CommandHelloCollapser(4).queue();

assertEquals("ValueForKey: 1", f1.get());

assertEquals("ValueForKey: 2", f2.get());

assertEquals("ValueForKey: 3", f3.get());

assertEquals("ValueForKey: 4", f4.get());

int numExecuted = HystrixRequestLog.getCurrentRequest().getAllExecutedCommands().size();

System.err.println("num executed: " + numExecuted);

// 断言此批次命令"Command Name:Hello Collapser"实际被执行了而却仅仅执行了它

// 一次或两次(由于这个例子使用了真实的定时器,源于调度程序的不确定性)

if (numExecuted > 2) {

fail("some of the commands should have been collapsed");

}

System.err.println("HystrixRequestLog.getCurrentRequest().getAllExecutedCommands(): " + HystrixRequestLog.getCurrentRequest().getAllExecutedCommands());

int numLogs = 0;

for (HystrixInvokableInfo> command : HystrixRequestLog.getCurrentRequest().getAllExecutedCommands()) {

numLogs++;

// 这个命令执行是我们所期望的

assertEquals("Command Name:Hello Collapser", command.getCommandKey().name());

System.err.println(command.getCommandKey().name() + " => command.getExecutionEvents(): " + command.getExecutionEvents());

// 确认是一个合并器的命令执行

assertTrue(command.getExecutionEvents().contains(HystrixEventType.COLLAPSED));

assertTrue(command.getExecutionEvents().contains(HystrixEventType.SUCCESS));

}

assertEquals(numExecuted, numLogs);

} finally {

context.shutdown();

}

}

请求上下文设置

这意味着在一个请求前必须执行如下语句:

HystrixRequestContext context = HystrixRequestContext.initializeContext();

在请求执行后执行以下语句:

context.shutdown();

在一个标准的java web应用中,可以使用 Servlet Filter (过滤器)初始化 HystrixRequestContext 生命周期,实现过滤器实现方式如下:

public class HystrixRequestContextServletFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HystrixRequestContext context = HystrixRequestContext.initializeContext();

try {

chain.doFilter(request, response);

} finally {

context.shutdown();

}

}

}

然后通过在web.xml中添加一段配置来启用所有进来的请求过滤器 ,示例如下:

HystrixRequestContextServletFilter

HystrixRequestContextServletFilter

com.netflix.hystrix.contrib.requestservlet.HystrixRequestContextServletFilter

HystrixRequestContextServletFilter

/*

声明

转帖请注明原贴地址:https://my.oschina.net/u/2342969/blog/1817093

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值