提交 e11f2bb9 编写于 作者: Y YunaiV

CacheFilter 过滤器

上级 26d2f181
......@@ -18,11 +18,25 @@ package com.alibaba.dubbo.cache;
/**
* Cache
*
* 缓存容器接口
*/
public interface Cache {
/**
* 添加键值
*
* @param key 键
* @param value 值
*/
void put(Object key, Object value);
/**
* 获得值
*
* @param key 键
* @return 值
*/
Object get(Object key);
}
}
\ No newline at end of file
......@@ -22,11 +22,19 @@ import com.alibaba.dubbo.common.extension.SPI;
/**
* CacheFactory
*
* 缓存工厂接口
*/
@SPI("lru")
public interface CacheFactory {
/**
* 获得缓存对象
*
* @param url URL 对象
* @return 缓存对象
*/
@Adaptive("cache")
Cache getCache(URL url);
}
}
\ No newline at end of file
......@@ -31,32 +31,47 @@ import com.alibaba.dubbo.rpc.RpcResult;
/**
* CacheFilter
*
* 缓存过滤器实现类
*/
@Activate(group = {Constants.CONSUMER, Constants.PROVIDER}, value = Constants.CACHE_KEY)
public class CacheFilter implements Filter {
/**
* CacheFactory$Adaptive 对象。
*
* 通过 Dubbo SPI 机制,调用 {@link #setCacheFactory(CacheFactory)} 方法,进行注入
*/
private CacheFactory cacheFactory;
public void setCacheFactory(CacheFactory cacheFactory) {
this.cacheFactory = cacheFactory;
}
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
// 方法开启 Cache 功能
if (cacheFactory != null && ConfigUtils.isNotEmpty(invoker.getUrl().getMethodParameter(invocation.getMethodName(), Constants.CACHE_KEY))) {
// 基于 URL + Method 为维度,获得 Cache 对象。
Cache cache = cacheFactory.getCache(invoker.getUrl().addParameter(Constants.METHOD_KEY, invocation.getMethodName()));
if (cache != null) {
// 获得 Cache Key
String key = StringUtils.toArgumentString(invocation.getArguments());
// 从缓存中获得结果。若存在,创建 RpcResult 对象。
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);
}
......
......@@ -25,14 +25,24 @@ import java.util.concurrent.ConcurrentMap;
/**
* AbstractCacheFactory
*
* Cache 工厂抽象类
*/
public abstract class AbstractCacheFactory implements CacheFactory {
/**
* Cache 集合
*
* key:URL
*/
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
@Override
public Cache getCache(URL url) {
// 获得 Cache 对象
String key = url.toFullString();
Cache cache = caches.get(key);
// 不存在,创建 Cache 对象,并缓存
if (cache == null) {
caches.put(key, createCache(url));
cache = caches.get(key);
......@@ -40,6 +50,12 @@ public abstract class AbstractCacheFactory implements CacheFactory {
return cache;
}
/**
* 创建 Cache 对象
*
* @param url URL
* @return Cache 对象
*/
protected abstract Cache createCache(URL url);
}
......@@ -31,32 +31,46 @@ import java.util.concurrent.TimeUnit;
/**
* JCache
*
* 与 [JSR107](https://jcp.org/en/jsr/detail?id=107) 集成,可以桥接各种缓存实现。
*/
public class JCache implements com.alibaba.dubbo.cache.Cache {
private final Cache<Object, Object> store;
public JCache(URL url) {
// 获得 Cache Key
String method = url.getParameter(Constants.METHOD_KEY, "");
String key = url.getAddress() + "." + url.getServiceKey() + "." + method;
// `"jcache"` 配置项,为 Java SPI 实现的全限定类名
// jcache parameter is the full-qualified class name of SPI implementation
String type = url.getParameter("jcache");
// 基于类型,获得 javax.cache.CachingProvider 对象,
CachingProvider provider = type == null || type.length() == 0 ? Caching.getCachingProvider() : Caching.getCachingProvider(type);
// 获得 javax.cache.CacheManager 对象
CacheManager cacheManager = provider.getCacheManager();
// 获得 javax.cache.Cache 对象
Cache<Object, Object> cache = cacheManager.getCache(key);
// 不存在,则进行创建
if (cache == null) {
try {
//configure the cache
// 设置 Cache 配置项
// configure the cache
MutableConfiguration config =
new MutableConfiguration<Object, Object>()
// 类型
.setTypes(Object.class, Object.class)
// 过期策略,按照写入时间过期。通过 `"cache.write.expire"` 配置项设置过期时间,默认为 1 分钟。
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MILLISECONDS, url.getMethodParameter(method, "cache.write.expire", 60 * 1000))))
.setStoreByValue(false)
// 设置 MBean
.setManagementEnabled(true)
.setStatisticsEnabled(true);
// 创建 javax.cache.Cache 对象
cache = cacheManager.createCache(key, config);
} catch (CacheException e) {
// 初始化 cache 的并发情况
// concurrent cache initialization
cache = cacheManager.getCache(key);
}
......@@ -65,10 +79,12 @@ public class JCache implements com.alibaba.dubbo.cache.Cache {
this.store = cache;
}
@Override
public void put(Object key, Object value) {
store.put(key, value);
}
@Override
public Object get(Object key) {
return store.get(key);
}
......
......@@ -25,6 +25,7 @@ import com.alibaba.dubbo.common.URL;
*/
public class JCacheFactory extends AbstractCacheFactory {
@Override
protected Cache createCache(URL url) {
return new JCache(url);
}
......
......@@ -24,20 +24,29 @@ import java.util.Map;
/**
* LruCache
*
* 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。
*/
public class LruCache implements Cache {
/**
* 缓存集合
*/
private final Map<Object, Object> store;
public LruCache(URL url) {
// `"cache.size"` 配置项,设置缓存大小
final int max = url.getParameter("cache.size", 1000);
// 创建 LRUCache 对象
this.store = new LRUCache<Object, Object>(max);
}
@Override
public void put(Object key, Object value) {
store.put(key, value);
}
@Override
public Object get(Object key) {
return store.get(key);
}
......
......@@ -25,6 +25,7 @@ import com.alibaba.dubbo.common.URL;
*/
public class LruCacheFactory extends AbstractCacheFactory {
@Override
protected Cache createCache(URL url) {
return new LruCache(url);
}
......
......@@ -24,26 +24,32 @@ import java.util.Map;
/**
* ThreadLocalCache
*
* 当前线程缓存,比如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。
*/
public class ThreadLocalCache implements Cache {
private final ThreadLocal<Map<Object, Object>> store;
private final ThreadLocal<Map<Object, Object>> store; // 线程变量
public ThreadLocalCache(URL url) {
this.store = new ThreadLocal<Map<Object, Object>>() {
@Override
protected Map<Object, Object> initialValue() {
return new HashMap<Object, Object>();
}
};
}
@Override
public void put(Object key, Object value) {
store.get().put(key, value);
}
@Override
public Object get(Object key) {
return store.get().get(key);
}
}
}
\ No newline at end of file
......@@ -25,6 +25,7 @@ import com.alibaba.dubbo.common.URL;
*/
public class ThreadLocalCacheFactory extends AbstractCacheFactory {
@Override
protected Cache createCache(URL url) {
return new ThreadLocalCache(url);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册