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 打开 https 链接,异常:“SSL: CERTIFICATE_VERIFY_FAILED”
Python3 打开 https 链接,异常:“SSL: CERTIFICATE_VERIFY_FAILED” 一.问题 Python2.7.9 之后,当使用urllib.urlopen打开一个 ht ...
- 02: shell中的if、case、for等语句
目录: 1.1 shell中常用运算符 1.2 使用if条件语句 1.3 shell 中的for循环 1.4 shell中的while循环语句 1.5 使用case分支语句 1.1 shell中常用运 ...
- 20145304 Exp3 免杀原理与实践
20145304 Exp3 免杀原理与实践 基础问题回答 (1)杀软是如何检测出恶意代码的? 检验特征码,包含特征码的代码会被杀软认为是恶意代码,例如一些常用恶意代码加壳后就有一个固定的代码会被认为是 ...
- CF620E New Year Tree 线段树 dfs序
luogu链接 题目大意: 有一个节点有颜色的树 操作1.修改子树的颜色 操作2.查询子树颜色的种类 注意,颜色种类小于60种 只有子树的操作,dfs序当然是最好的选择 dfs序列是什么,懒得讲了,自 ...
- 动态规划模板1|LIS最长上升子序列
LIS最长上升子序列 dp[i]保存的是当前到下标为止的最长上升子序列的长度. 模板代码: int dp[MAX_N], a[MAX_N], n; int ans = 0; // 保存最大值 for ...
- 【Apache】的运营之道
1.“一个修修补补”的服务? 大家可能听说过 Apache 是一个双关语 “a patchy Web server”,意思为一个修修补补的 web 服务,即通过一系列的补丁做的服务.但是这并不是 Ap ...
- 【第三十五章】 metrics(3)- codahale-metrics基本使用
<!-- metrics --> <dependency> <groupId>io.dropwizard.metrics</groupId> <a ...
- Java初始化块的作用
1.使代码更简洁 eg: public class Test { private void init() { System.out.println("初始化状态"); } publ ...
- UVa 11134 传说中的车
https://vjudge.net/problem/UVA-11134 题意:在n*n的棋盘上放n个车,使得任意两个车不相互攻击,且第i个车在一个给定的矩形Ri之内.用4个整数xli,yli,xri ...
- 获取CheckBox的值
前台获取 function chkCheckBox() { var code_arr = new Array(); //定义一数组 $('.C_B').each(function () { if ($ ...