Dubbo 接口调用结果缓存的实现分析

来源:互联网 发布:windows黑体字体下载 编辑:程序博客网 时间:2024/05/18 19:45

结果缓存,用于加速热门数据的访问速度,Dubbo提供声明式缓存,以减少用户加缓存的工作量。

1 配置说明

配置如:

<dubbo:reference interface="com.foo.BarService" cache="lru" />

或:

<dubbo:reference interface="com.foo.BarService">    <dubbo:method name="findBar" cache="lru" /></dubbo:reference>

当配置完毕后,客户端发起一次调用请求,dubbo会先去查询缓存,如果能找到结果,则返回。否则,执行完整的调用请求,最后将结果缓存。

2 缓存的类型

结果缓存体系有两部分组成,分别是缓存工厂(CacheFactory),缓存(CacheFactory)。缓存工厂用来创建缓存,来缓存某个方法的结果。框架自带的缓存工厂有如下几种。

这里写图片描述

而框架自带的对应的缓存类型与缓存工厂对应。
这里写图片描述

第一节配置说明使用的缓存类型为LRU(最近最少使用)。也可以根据dubbo提供的扩展机制实现自定义缓存。只要分别实现缓存工厂和缓存即可。

3 结果缓存的实现分析

在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<Object, Object> store;

ThreadLocalCache为:

private final ThreadLocal<Map<Object, Object>> store;

JCache为:

private final Cache<Object, Object> store;

Cache工厂(CacheFactory)都继承自AbstractCacheFactory类。

public abstract class AbstractCacheFactory implements CacheFactory {    private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();    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留给具体的工厂类去实现,根据缓存类型的不同,创建不同的缓存对象。

4 参考:

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源码

原创粉丝点击