缓存与合并请求
缓存注解
在6.3章节中,讲述了Hystrix的缓存功能,在Spring
Cloud中,同样支持使用缓存,并且可以通过注解来实现。根据前面章节可知,缓存与合并请求功能,需要先初始化请求上下文才能实现。新建一个javax.servlet.Filter,用于创建与销毁Hystrix的请求上下文,请见代码清单6-9。
代码清单6-19:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\HystrixFilter.java
@WebFilter(urlPatterns
= "/*", filterName = "hystrixFilter")
public
class HystrixFilter implements Filter {
public
void init(FilterConfig filterConfig) throws ServletException
{
}
public
void doFilter(ServletRequest request, ServletResponse
response,
FilterChain
chain) throws IOException, ServletException {
HystrixRequestContext context =
HystrixRequestContext
.initializeContext();
try
{
chain.doFilter(request,
response);
}
finally {
context.shutdown();
}
}
public
void destroy()
{
}
}
编写服务方法,使用@CacheResult注解进行修饰,请见代码清单6-20。
代码清单6-20:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\cache\CacheService.java
@Component
public
class CacheService {
@CacheResult
@HystrixCommand
public
Person getPerson(Integer id)
{
System.out.println("执行getPerson方法");
Person
p = new Person();
p.setId(id);
p.setName("angus");
return
p;
}
}
注意服务方法中,被调用一次就会进行一次控制台输出。在控制器的方法中,调用多次getPerson方法,控制器代码请见代码清单6-21。
代码清单6-21:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\InvokerController.java
@RequestMapping(value
= "/cache1/{personId}", method = RequestMethod.GET,
produces
= MediaType.APPLICATION_JSON_VALUE)
public
Person testCacheResult(@PathVariable Integer personId) {
//调用多次服务
for(int
i =0;
i <3;
i++) {
Person
p = cacheService.getPerson(personId);
System.out.println("控制器调用服务"
+ i);
}
return
new Person();
}
控制器中调用了多次服务方法,也就是用户发送请求后,会执行多次服务方法,启动“服务调用者”,访问以下地址:http://localhost:9000/cache1/1,控制台输出如下:
执行getPerson方法
控制器调用服务0
控制器调用服务1
控制器调用服务2
根据输出结果可知,在一次用户请求的过程中,服务方法只执行了一次,缓存生效。缓存的注解主要有以下3个:
@CacheResult:该注解修饰方法,表示被修饰的方法返回结果将会被缓存,需要与@HystrixCommand一起使用。
@CacheRemove:用于修饰方法让缓存失效,需要与@CacheResult的缓存key关联。
@CacheKey:用于修饰方法参数,表示该参数作为缓存的key。
前面的例子使用了@CacheResult注解,下面的代码片断,结合@CacheResult与@CacheRemove一起使用:
@CacheResult()
@HystrixCommand(commandKey
= "removeKey")
public
String cacheMethod(String name) {
return
"hello";
}
@CacheRemove(commandKey
= "removeKey")
@HystrixCommand
public
String updateMethod(String name) {
return
"update";
}
以上代码片断中的cacheMethod方法,使用的缓存key为“removeKey”,方法updateMethod被调用后,将会删除key为“updateMethod”的缓存。关于3个缓存注解更深入的使用,本小节不再赘述,读者可以自行测试。
合并请求注解
在Spring
Cloud中,同样支持合并请求,在一次HTTP请求的过程中,收集一段时间内的相同请求,放到一个批处理命令中执行。实现合并请求,同样需要先初始化请求上下文,具体请参见6.4.4中的Filter。接下来,编写服务类,请见代码清单6-22。
代码清单6-22:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\collapse\CollapseService.java
@Component
public
class CollapseService {
//配置收集1秒内的请求
@HystrixCollapser(batchMethod ="getPersons",
collapserProperties =
{
@HystrixProperty(name = "timerDelayInMilliseconds", value =
"1000")
}
)
publicFuturegetSinglePerson(Integer
id) {
System.out.println("执行单个获取的方法");
return
null;
}
@HystrixCommand
public
List getPersons(List ids) {
System.out.println("收集请求,参数数量:"
+ ids.size());
List
ps = new ArrayList();
for
(Integer id : ids) {
Person
p = new Person();
p.setId(id);
p.setName("crazyit");
ps.add(p);
}
return
ps;
}
}
代码清单中,最后真实执行的方法为“getPersons”,getSinglePerson方法使用了@HystrixCollapser注解来修饰,会收集1秒内调用getSinglePerson的请求,放到getPersons方法中进行批处理。控制器中调用多次getSinglePerson方法,如代码清单6-23所示。
代码清单6-23:
codes\06\6.4\spring-hystrix-invoker\src\main\java\org\crazyit\cloud\InvokerController.java
@RequestMapping(value
= "/collapse", method = RequestMethod.GET,
produces
= MediaType.APPLICATION_JSON_VALUE)
public
String testCollapse() throws Exception {
//连续执行3次请求
Future
f1 = collapseService.getSinglePerson(1);
Future
f2 = collapseService.getSinglePerson(2);
Future
f3 = collapseService.getSinglePerson(3);
Person
p1 = f1.get();
Person
p2 = f2.get();
Person
p3 = f3.get();
System.out.println(p1.getId()
+ "---" + p1.getName());
System.out.println(p2.getId()
+ "---" + p2.getName());
System.out.println(p3.getId()
+ "---" + p3.getName());
return
"";
}
异步执行了3次getSinglePerson方法,启动“服务调用者”,访问以下地址:http://localhost:9000/collapse,控制台输出如下:
收集请求,参数数量:3
1---crazyit
2---crazyit
3---crazyit
根据输出结果可知,最终只执行了getPersons方法。相对于直接使用Hystrix,Spring
Cloud中合并请求较为简单,合并处理器已经由@HystrixCollapser注解帮我们实现,我们仅关心真正命令的执行即可。