变通实现微服务的per request以提高IO效率(三)
2016-12-02 15:00
337 查看
效率
变通实现微服务的per request以提高IO效率(二)遗留一个问题,如何正确的释放存储在ThreadLocal中的缓存,最理由就是在我们请求的方法执行完成后去清除缓存。Filter
由于我的项目是基于dubbo的,所以可以利用dubbo提供的Filter机制去完成这件事情,可以看下filter的地位:最终的效果:
创建ThreadLocalCacheFilter
创建一个类让其实现Filter接口,就一个方法invoke,这个invoke方法的功能类似于AOP的Around方法,我们想清除缓存就有地方操作了,只需要在return的前面,invoker.invoke方法后面添加相应的清除逻辑即可达到目的。由于缓存是线程独有的,所以直接清空就可以。由于Filter加载机制问题,在Filter中使用Spring的注解是有点问题的,暂时是通过手动获取Bean的方式来加载cacheManager,后面在看dubbo的filter加载机制时会有简单提到。大家如果有其它好的方案可以告诉我
@Activate public class ThreadLocalCacheFilter implements Filter { private Logger logger = LoggerFactory.getLogger(getClass().getName()); @Autowired private CacheManager cacheManager; private void clearCache(){ if(null==cacheManager){ ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext(); cacheManager= appCtx.getBean(ThreadLocalCacheManager.class); } Collection<String> cacheNames= this.cacheManager.getCacheNames(); if(null!=cacheNames) { for(String cacheName :cacheNames) { this.cacheManager.getCache(cacheName).clear(); } } } @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { Result result=invoker.invoke(invocation); this.logger.info("release cache start"); this.clearCache(); this.logger.info("release cache end"); return result; } }
@Active注解
要想激活filter,我们需要在创建的自定义filter类上加载@Active注解,看下它的相关参数,也可以不配置
group,条件之一,指定是服务端还是消费端
value,条件之一,一般就是这个filter的英文名称,在dubbo配置文件中使用的
before,排序的信息,比如排在哪些filter之前
after,排序的信息,比如排在哪些filter之后
order,排序的信息,应该是值越小排在最前面
加载Filter
编写的扩展filter,dubbo需要加载成功后才能使用,dubbo总共从resource下面的三个目录中加载filterMETA-INF/services/
META-INF/dubbo/
META-INF/dubbo/internal/
创建纯文件文件com.alibaba.dubbo.rpc.Filter放入对应的目录,然后写入需要使用的filter信息
threadLocalCacheFilter=com.filter.ThreadLocalCacheFilter
应用Filter
在dubbo配置文件中增加如下内容:<dubbo:provider filter="threadLocalCacheFilter" />
Dubbo Filter
dubbo有这样一个类ProtocolFilterWrapper,它负责加载项目中所有的filter,并负责链式调用。想学习设计模式的可以看看这个类是如何使用职责链模式的
这里只看一个方法就可以了:
ExtensionLoader加载所以实现了Filter接口的类
根据过滤条件过滤filter,里面有排序
循环调用所有符合条件且经过排序的filter
注意变量next,当前方法在执行invoke方法时,将调用传递到了next。这里应该会有最后一个终结器来处理实际方法的执行。
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) { Invoker<T> last = invoker; List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); if (filters.size() > 0) { for (int i = filters.size() - 1; i >= 0; i --) { final Filter filter = filters.get(i); final Invoker<T> next = last; last = new Invoker<T>() { public Class<T> getInterface() { return invoker.getInterface(); } public URL getUrl() { return invoker.getUrl(); } public boolean isAvailable() { return invoker.isAvailable(); } public Result invoke(Invocation invocation) throws RpcException { return filter.invoke(next, invocation); } public void destroy() { invoker.destroy(); } @Override public String toString() { return invoker.toString(); } }; } } return last; }
总结
结过三篇笔记,从最初的Context问题,到缓存的释放,基本可以非常方便的使用请求级的缓存了。这里需要注意的是需要明确哪些方案是适合做请求级缓存的。比如查询用户,有些操作中先插入用户然后再查询,如果查询的是被标记了请求级缓存的方法就会有问题。相关文章推荐
- 变通实现微服务的per request以提高IO效率(二)
- 变通实现微服务的per request以提高IO效率
- 变通实现微服务的per request以提高IO效率
- 关于java的io读写,缓冲区是如何提高读写效率的???
- 关于c 实现希望提高效率的探讨
- 提高Request集合的效率
- 转贴C/C++用移位实现乘除法运算,提高运行效率
- C/C++用移位实现乘除法运算,提高运行效率
- 正则用(?>…)实现固化分组提高效率
- Nhibernate one Session per Request的实现
- 用powershell脚本实现Andoird为不同市场编译、签名自动化,效率极大提高
- 无闪烁刷屏技术的实现如何提高绘图的效率
- 使用JRebel实现Web项目热部署, 提高开发效率
- oracle服务启动批处理 提高开机及运行效率
- 使用异或实现两个数的换位,不需要中间变量,提高效率
- 发挥缓存的威力,提高代码效率,及如何实现16位浮点数
- C/C++用移位实现乘除法运算,提高运行效率
- FAQ,提高服务台效率的利器
- 基于.NET的分词软件设计与实现V5.0--使用Hashtable和HashSet<T>提高分词效率