前言
在SpringMVC中使用时,在一次请求Controller时,其中多次调用被HystrixCommand封装的依赖时,如果配置了缓存,除第一次外,后面访问会走缓存。本次请求返回后,缓存即失效。
再一次请求Controller时,调用被HystrixCommand封装的依赖时,缓存又重新建立,返回后又被销毁。
即缓存的生命周期只限一次请求中。
请求缓存在run()和construct()执行之前生效,所以可以有效减少不必要的线程开销
通过HystrixCommand类实现
继承HystrixCommand或HystrixObservableCommand,覆盖getCacheKey()方法,指定缓存的key,开启缓存配置。
具体代码,可见前文。
通过注解实现
- 首先,编写Filter初始化HystrixRequestContext
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
36package com.fuyi.hystrix.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
public class HystrixContextInitFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HystrixRequestContext context = HystrixRequestContext.initializeContext();
try {
chain.doFilter(request, response);
} finally {
context.shutdown();
}
}
@Override
public void destroy() {
}
} - service实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Service("userService")
public class UserService {
// 该注解标记请求依赖的结果应该被缓存
// 默认缓存key使用方法的所有参数,可自定义,下文说
@CacheResult
@HystrixCommand(groupKey = "getUserById")
public String getUserById(String id) {
System.out.println("from db query user in thread : " + Thread.currentThread().getName());
return "fuyi";
}
// 该注解让指定的commandKey的缓存结果失效
@CacheRemove(commandKey = "getUserById")
@HystrixCommand(groupKey = "updateUserById")
public void updateUserById(String id) {
System.out.println("update user");
}
} - controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Controller
public class HelloController {
@Autowired
private UserService userService;
@RequestMapping("/getUserById")
@ResponseBody
public String getUserById(String id) {
userService.getUserById(id); // out
userService.getUserById(id);
userService.updateUserById(id);
userService.getUserById(id); // out
return userService.getUserById(id);
}
} - 启动类
1 | @SpringBootApplication |
测试
- 访问
http://localhost:1111/getUserById?id=1
- 结果
1 | from db query user in thread : hystrix-getUserById-3 |
第一次访问时,查询db, 更新后,会再查一次,其他时不会查db.
自定义缓存key
通过@CacheResult和@CacheRemove的cacheKeyMethod属性定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24@Service("userService")
public class UserService {
// 该注解标记请求依赖的结果应该被缓存
// 缓存key通过cacheKeyMethod属性指定的方法生成
@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(groupKey = "getUserById")
public String getUserById(String id) {
System.out.println("from db query user in thread : " + Thread.currentThread().getName());
return "fuyi";
}
// 生成缓存key的方法
public String getCacheKey(String id) {
return id;
}
// 该注解让指定的commandKey的缓存结果失效
@CacheRemove(commandKey = "getUserById", cacheKeyMethod = "getCacheKey")
@HystrixCommand(groupKey = "updateUserById")
public void updateUserById(String id) {
System.out.println("update user");
}
}通过@CacheKey注解配合方法参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Service("userService")
public class UserService {
// 该注解标记请求依赖的结果应该被缓存
// 通过@CacheKey指定参数id为缓存key
@CacheResult
@HystrixCommand(groupKey = "getUserById")
public String getUserById( @CacheKey(value = "id") String id) {
System.out.println("from db query user in thread : " + Thread.currentThread().getName());
return "fuyi";
}
// 该注解让指定的commandKey的缓存结果失效
@CacheRemove(commandKey = "getUserById")
@HystrixCommand(groupKey = "updateUserById")
public void updateUserById(String id) {
System.out.println("update user");
}
}参数为对象时:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20@Service("userService")
public class UserService {
// 该注解标记请求依赖的结果应该被缓存
// 通过@CacheKey指定User对象中的id属性为缓存key
@CacheResult
@HystrixCommand(groupKey = "getUserById")
public String getUserById( @CacheKey(value = "id") User user) {
System.out.println("from db query user in thread : " + Thread.currentThread().getName());
return "fuyi";
}
// 该注解让指定的commandKey的缓存结果失效
@CacheRemove(commandKey = "getUserById")
@HystrixCommand(groupKey = "updateUserById")
public void updateUserById(String id) {
System.out.println("update user");
}
}需要注意,如果以上两者同时指定,则前者优先级高于后者,即cacheKeyMethod属性配置优先级高于@CacheKey配置。