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的更多相关文章

  1. Dubbo的全局Filter配置

    前言: 之前也写过dubbo的filter的文章, 后来和同事也有过交流, 才发生自己对dubbo的filter的机制, 还是存在一些误解, 尤其是自定义filter的定位, 不是那么清晰. 本文主要 ...

  2. dubbo系列六、SPI扩展Filter隐式传参

    一.实现Filter接口 1.消费者过滤器:ConsumerTraceFilter.java package com.dubbo.demo.Filter; import com.alibaba.dub ...

  3. 《Lua程序设计》9.2 管道(pipe)与过滤器(filter) 包含使用协同函数实现“生产者——消费者”问题的实例代码

    一个关于协同程序的经典示例是“生产者-消费者”问题.这其中涉及到两个函数,一个函数不断地产生值(比如从一个文件中读取值),另一个则不断地消费这些值(比如将这些值写到另一个文件).通常,这两个函数大致是 ...

  4. MYSQL提权总结

    最近在测试一个项目,遇到了MYSQL数据库,想尽办法提权,最终都没有成功,很是郁闷,可能是自己很久没有研究过提权导致的吧,总结一下MYSQL提权的各种姿势吧,权当复习了.关于mysql提权的方法也就那 ...

  5. [转载]协程-cooperative multitasking

    [转载]协程三讲 http://ravenw.com/blog/2011/08/24/coroutine-part-1-defination-and-classification-of-corouti ...

  6. Lua中的协同程序 coroutine

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  7. mof提权带回显带清楚命令版本.php

    <?php $path="c:/caonimei.txt"; session_start(); if(!empty($_POST['submit'])){ setcookie ...

  8. 无shell情况下的mysql远程mof提权利用方法详解

    扫到一个站的注入<ignore_js_op> 在havij中得到mysql数据库中mysql库保存的数据库密码:<ignore_js_op> 有时候发现1.15版的还是最好用, ...

  9. chapter9_2 管道与过滤器

    一个关于协同程序的经典示例就是“生产者-消费者”的问题. 一个不断产生值,一个不断消费这些值.比如: function producer() while true do local x = io.re ...

随机推荐

  1. NFS常用命令

    1.客户端查看服务端可挂载卷 showmount -t 服务端IP 2.不重启加载NFS配置文件 exportfs -avr

  2. 20145105 《Java程序设计》第10周学习总结

    20145105 <Java程序设计>第10周学习总结 教材学习内容总结 JAVA网络编程 一.网络概述 (一)计算机网络概述 网络编程的实质就是两个(或多个)设备(例如计算机)之间的数据 ...

  3. 20145118 《Java程序设计》课程总结

    20145118 <Java程序设计>课程总结 每周读书笔记连接汇总 假期笔记 http://www.cnblogs.com/cy1123/p/5224305.html 第一周读书笔记 h ...

  4. android 实践项目四

    android 实践项目四 本周主要是开发android baidumap实现公交的查询 1.权限的取得和对屏幕的支持 <uses-permission android:name="a ...

  5. 小工具:word表格文字转化成insert语句

    群里的一个朋友有个需要,要让把word里的表格数据插入到数据库里面. 我的思路是,把格式化的数据转成insert语句,然后去执行就可以了. 要求的insert语句格式是:'insert into xx ...

  6. git的软件安装

    1.Git for Winodws 1.*的版本   https://github.com/msysgit/msysgit/releases 2.*的版本   https://github.com/g ...

  7. 【基础配置】Dubbo的配置及使用

    1. Dubbo是什么? Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案.简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需 ...

  8. jquery 浏览器打印

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  9. 网络量化——Quantized Convolutional Neural Networks for Mobile Devices

    论文地址:https://arxiv.org/abs/1512.06473 源码地址:https://github.com/jiaxiang-wu/quantized-cnn 1. 主要思想 这篇文章 ...

  10. Android程序示例

    目录 Android代码示例 OptionsMenu ImageButton CheckBox & RadioButton Context Menu快捷菜单 Key Event ListVie ...