结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。
配置如:
interface="com.foo.BarService" cache="lru" />
或:
<dubbo:reference interface="com.foo.BarService">
<dubbo:method name="findBar" cache="lru" />
dubbo:reference>
当配置完毕后,客户端发起一次调用请求,dubbo会先去查询缓存,如果能找到结果,则返回。否则,执行完整的调用请求,最后将结果缓存。
结果缓存体系有两部分组成,分别是缓存工厂(CacheFactory),缓存(CacheFactory)。缓存工厂用来创建缓存,来缓存某个方法的结果。框架自带的缓存工厂有如下几种。
第一节配置说明使用的缓存类型为LRU(最近最少使用)。也可以根据dubbo提供的扩展机制实现自定义缓存。只要分别实现缓存工厂和缓存即可。
在dubbo调用链创建一文中知道,dubbo对目标方法调用前会先经过过滤器链。而结果缓存的实现正是通过com.alibaba.dubbo.cache.filter.CacheFilter类来实现。
该类的实现如下。
public class CacheFilter implements Filter {
private CacheFactory cacheFactory;
public void setCacheFactory(CacheFactory cacheFactory) {
this.cacheFactory = cacheFactory;
}
public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
if (cacheFactory != null && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.CACHE_KEY))) {
Cache cache = cacheFactory.getCache(invoker.getUrl().addParameter(Constants.METHOD_KEY, invocation.getMethodName()));
if (cache != null) {
String key = StringUtils.toArgumentString(invocation.getArguments());
if (cache != null && key != null) {
Object value = cache.get(key);
if (value != null) {
return new RpcResult(value);
}
Result result = invoker.invoke(invocation);
if (! result.hasException()) {
cache.put(key, result.getValue());
}
return result;
}
}
}
return invoker.invoke(invocation);
}
}
其主流程为:
1.根据调用方法的相关参数获取缓存对象。
2.以方法参数为key,去查找结果。
3.缓存中若查找到结果则返回,否则继续调用,最后缓存此次调用结果。
dubbo中提供的cache接口,有两个方法,put及get。
public interface Cache {
void put(Object key, Object value);
Object get(Object key);
}
而实现类中缓存的数据结构根据实现不同而变化。
LRU cache为:
private final Map
ThreadLocalCache为:
private final ThreadLocal
JCache为:
private final Cache
Cache工厂(CacheFactory)都继承自AbstractCacheFactory类。
public abstract class AbstractCacheFactory implements CacheFactory {
private final ConcurrentMap caches = new ConcurrentHashMap();
public Cache getCache(URL url) {
String key = url.toFullString();
Cache cache = caches.get(key);
if (cache == null) {
caches.put(key, createCache(url));
cache = caches.get(key);
}
return cache;
}
protected abstract Cache createCache(URL url);
}
可以看到在这个类中通过ConcurrentMap来保存不同key,所对应的Cache,例如方法A的缓存CacheA,B的CacheB。并提供get方法来获取对应key的缓存对象。此外提供了抽象方法createCache留给具体的工厂类去实现,根据缓存类型的不同,创建不同的缓存对象。
1、dubbo 官方文档
http://dubbo.io/User+Guide-zh.htm#UserGuide-zh-%E7%BB%93%E6%9E%9C%E7%BC%93%E5%AD%98
2、dubbo 2.8.4源码