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. P2414 [NOI2011]阿狸的打字机

    P2414 [NOI2011]阿狸的打字机 AC自动机+树状数组 优质题解 <------题目分析 先AC自动机搞出Trie图 然后根据fail指针建一只新树 把树映射(拍扁)到一个序列上,用树 ...

  2. QTQuick控件基础(2)

    import QtQuick 2.2import QtQuick.Controls 1.2import QtQuick.Window 2.1ApplicationWindow {    visible ...

  3. Android实践项目汇报(一)

    # 我要做的是Google天气客户端 一.Need(需求): 1. 功能性需求分析 天气预报客户端,顾名思义就是为用户提供实时准确的天气信息,方便用户出行生活.根据用户日常需求,软件实现后所达到的功能 ...

  4. poj 2369 Permutations - 数论

    We remind that the permutation of some final set is a one-to-one mapping of the set onto itself. Les ...

  5. Win32 文件拖拽

    1.响应系统消息  WM_DROPFILES 2.在响应函数里面获取拖拽文件路径 LRESULT OnDropFiles(UINT uMsg, WPARAM wParam, LPARAM lParam ...

  6. 设置控件如ImageButton可见与否

    继承view的控件有三种ui属性: 1.setVisibility(View.Gone); 不可见,不占有空间 2.setVisibility(View.VISIBLE); 可见 3.setVisib ...

  7. jQuery 源码分析:当 selector 传来一个函数时,怎么进行处理?

    本文章为 0.9 版本,将会在稍后润色更新.本文使用的 jQuery 版本为 3.4.0 我们知道使用 $ 操作符时,可以往里面塞很多类型的参数,字符串,对象,函数...,jQuery 会根据不同的参 ...

  8. [Shiro] - 基于URL配置动态权限

    基于shiro进阶 更改了数据库表 之前的PageController是通过@RequiresPermissions和@RequiresRoles进行是否有权限/是否有角色的判定调用@RequestM ...

  9. UVa 10723 电子人的基因(LCS)

    https://vjudge.net/problem/UVA-10723 题意: 输入两个A~Z组成的字符串,找一个最短的串,使得输入的两个串均是它的子序列,另外还需要统计长度最短的串的个数. 思路: ...

  10. .net 与 java 开发微服务对比

    java+spring boot+maven对比.net 优势: 1. spring 自身带的ioc 比.net 更简单易用. 2. spring actuator的健康检测等运行时状态查看功能很赞. ...