consumer filter
ProtocolFilterWrapper中buildInvokerChain方法把Filter链在一起,调用执行的时候,逐个执行filter,最后执行filter中的invoker。
//ProtocolFilterWrapper
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;
}
上面代码中,last的视图:

我们这样看:匿名内部类 new Invoker<T> { ... }中,
封装了final Filter filter,final Invoker<T> next,还有final Invoker<T> invoker,然后把filter链在一起。
consumer端一共有3个filter:ConsumerContextFilter, MonitorFilter, FutureFilter
1. ConsumerContextFilter 对RpcContext做设置和清理
@Activate(group = Constants.CONSUMER, order = -10000)
public class ConsumerContextFilter implements Filter { public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext()
.setInvoker(invoker)
.setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0)
.setRemoteAddress(invoker.getUrl().getHost(),
invoker.getUrl().getPort());
if (invocation instanceof RpcInvocation) {
((RpcInvocation)invocation).setInvoker(invoker);
}
try {
return invoker.invoke(invocation);
} finally {
RpcContext.getContext().clearAttachments();
}
} }
2. MonitorFilter 统计接口方法调用信息
3. FutureFilter 处理异步调用
@Activate(group = Constants.CONSUMER)
public class FutureFilter implements Filter {}
在DubboInvoker.doInvoke方法中,
如果是异步,则在RpcContext设置Future,并返回空的RpcResult:
ResponseFuture future = currentClient.request(inv, timeout) ;
RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
return new RpcResult();
如果是同步,则调用Future.get()方法而阻塞:
RpcContext.getContext().setFuture(null);
ResponseFuture future = currentClient.request(inv, timeout);
Result result = (Result)future.get();
return result;
FutureAdapter实现了Future接口,内部封装了一个ResponseFuture对象。
ResponseFuture是一个接口,DefaultFuture是主要实现类。
FutureFilter.asyncCallback()为DefaultFuture设置回调函数:
//FutureFilter.asyncCallback
ResponseFuture future = ((FutureAdapter<?>)f).getFuture();
future.setCallback(new ResponseCallback() {
public void done(Object rpcResult) {
...
}
public void caught(Throwable exception) {
...
}
});
//DefaultFuture
public void setCallback(ResponseCallback callback) {
if (isDone()) {
invokeCallback(callback);
} else {
boolean isdone = false;
lock.lock();
try{
if (!isDone()) {
this.callback = callback;
} else {
isdone = true;
}
}finally {
lock.unlock();
}
if (isdone){
invokeCallback(callback);
}
}
}
private void invokeCallback(ResponseCallback c){
ResponseCallback callbackCopy = c;
if (callbackCopy == null){
throw new NullPointerException("callback cannot be null.");
}
c = null;
Response res = response;
if (res == null) {
throw new IllegalStateException("response cannot be null. url:"+channel.getUrl());
} if (res.getStatus() == Response.OK) {
try {
callbackCopy.done(res.getResult());
} catch (Exception e) {
logger.error("callback invoke error .reasult:" + res.getResult() + ",url:" + channel.getUrl(), e);
}
} else if (res.getStatus() == Response.CLIENT_TIMEOUT || res.getStatus() == Response.SERVER_TIMEOUT) {
try {
TimeoutException te = new TimeoutException(res.getStatus() == Response.SERVER_TIMEOUT, channel, res.getErrorMessage());
callbackCopy.caught(te);
} catch (Exception e) {
logger.error("callback invoke error ,url:" + channel.getUrl(), e);
}
} else {
try {
RuntimeException re = new RuntimeException(res.getErrorMessage());
callbackCopy.caught(re);
} catch (Exception e) {
logger.error("callback invoke error ,url:" + channel.getUrl(), e);
}
}
}
consumer filter的更多相关文章
- Dubbo的全局Filter配置
前言: 之前也写过dubbo的filter的文章, 后来和同事也有过交流, 才发生自己对dubbo的filter的机制, 还是存在一些误解, 尤其是自定义filter的定位, 不是那么清晰. 本文主要 ...
- dubbo系列六、SPI扩展Filter隐式传参
一.实现Filter接口 1.消费者过滤器:ConsumerTraceFilter.java package com.dubbo.demo.Filter; import com.alibaba.dub ...
- 《Lua程序设计》9.2 管道(pipe)与过滤器(filter) 包含使用协同函数实现“生产者——消费者”问题的实例代码
一个关于协同程序的经典示例是“生产者-消费者”问题.这其中涉及到两个函数,一个函数不断地产生值(比如从一个文件中读取值),另一个则不断地消费这些值(比如将这些值写到另一个文件).通常,这两个函数大致是 ...
- MYSQL提权总结
最近在测试一个项目,遇到了MYSQL数据库,想尽办法提权,最终都没有成功,很是郁闷,可能是自己很久没有研究过提权导致的吧,总结一下MYSQL提权的各种姿势吧,权当复习了.关于mysql提权的方法也就那 ...
- [转载]协程-cooperative multitasking
[转载]协程三讲 http://ravenw.com/blog/2011/08/24/coroutine-part-1-defination-and-classification-of-corouti ...
- Lua中的协同程序 coroutine
Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...
- mof提权带回显带清楚命令版本.php
<?php $path="c:/caonimei.txt"; session_start(); if(!empty($_POST['submit'])){ setcookie ...
- 无shell情况下的mysql远程mof提权利用方法详解
扫到一个站的注入<ignore_js_op> 在havij中得到mysql数据库中mysql库保存的数据库密码:<ignore_js_op> 有时候发现1.15版的还是最好用, ...
- chapter9_2 管道与过滤器
一个关于协同程序的经典示例就是“生产者-消费者”的问题. 一个不断产生值,一个不断消费这些值.比如: function producer() while true do local x = io.re ...
随机推荐
- Python3基础 global 使函数中的局部变量升格为全局变量
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Spring通过ApplicationContext主动获取bean
有些场景无法通过AutoWired和compoment注解传递进来,于是希望通过Spring context主动去获取beandemo: package com.qhong.Util; import ...
- Ubuntu 16.04设置IP、网关、DNS
说明:在网上给的教程上面通常会有这样的一个误导思路,按照配置文件设置后会不生效的问题,甚至没有一点效果,经过排查发现Linux下设置IP这个话题的入口线索应该分为两种:1为Server版,2为Desk ...
- 2017年P4中国峰会北京站 会议小结
2017 P4 中国峰会 北京 本次会议依然侧重介绍P4,并highlight P4的benifit,大致分为以下几类: 1.学术界 - 未来网络的发展,为何提出P4技术? 未来网络和实体经济.其他学 ...
- 【Coursera】Technology :Fifth Week(1)
Store and Forward Networking 在长途连接中,路由的数量 取决于 最优路径(花费最少).也就是说被地理条件所限制. 所以 Store and Forward Networki ...
- HDU 5889 Barricade(最短路+最小割)
http://acm.hdu.edu.cn/showproblem.php?pid=5889 题意: 给出一个图,帝国将军位于1处,敌军位于n处,敌军会选择最短路到达1点.现在帝国将军要在路径上放置障 ...
- spring boot 捕获filter异常 统一返回处理结果
如前面的文章所述,controller中抛出的异常我们使用ControllerAdvice来处理: @RestControllerAdvice @Slf4j public class GlobalEx ...
- booststrap select2的应用总结
本身对前端js了解不是特别多,在项目中,遇到很多前端的问题,有时间整理一下,有不对的地方,不吝赐教,多多批评指正. 在项目中,遇到最多的select下拉框情景,莫过于多选和单选了 单选是很容易理解的, ...
- mvc ---- ajax 提交过来的Json格式如何处理(解析)
前台传过来的不是一个对象,而是一个Json字符串怎么办 ? 如: {","contents":"<p>lsdfjlsdjflsdf</p> ...
- Apache的安装与卸载
安装 1.下载压缩包并解压到D盘根目录(目录自定义) 2.用记事本打开D:\Apache\conf\httpd.conf,找到Define SRVROOT 把值改为上一步的路径,如Define SRV ...