Dubbo Filter机制概述
https://blog.csdn.net/prestigeding/article/details/82085705
从上文可知,在服务的调用或消费端发送请求命令中,Dubbo引入过滤器链机制来实现功能的包装(或扩展)。Dubbo很多功能,例如泛化调用、并发控制等都是基于Filter机制实现的,系统默认的Filter在/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter文件中定义,内容如下:
echo=com.alibaba.dubbo.rpc.filter.EchoFilter
generic=com.alibaba.dubbo.rpc.filter.GenericFilter
genericimpl=com.alibaba.dubbo.rpc.filter.GenericImplFilter
token=com.alibaba.dubbo.rpc.filter.TokenFilter
accesslog=com.alibaba.dubbo.rpc.filter.AccessLogFilter
activelimit=com.alibaba.dubbo.rpc.filter.ActiveLimitFilter
classloader=com.alibaba.dubbo.rpc.filter.ClassLoaderFilter
context=com.alibaba.dubbo.rpc.filter.ContextFilter
consumercontext=com.alibaba.dubbo.rpc.filter.ConsumerContextFilter
exception=com.alibaba.dubbo.rpc.filter.ExceptionFilter
executelimit=com.alibaba.dubbo.rpc.filter.ExecuteLimitFilter
deprecated=com.alibaba.dubbo.rpc.filter.DeprecatedFilter
compatible=com.alibaba.dubbo.rpc.filter.CompatibleFilter
timeout=com.alibaba.dubbo.rpc.filter.TimeoutFilter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
以其中一个来说明一下Filter的定义要素:
/**
* EchoInvokerFilter
*/
@Activate(group = Constants.PROVIDER, order = -110000) // @2
public class EchoFilter implements Filter { // @1
@Override
public Result invoke(Invoker<?> invoker, Invocation inv) throws RpcException {
if (inv.getMethodName().equals(Constants.$ECHO) && inv.getArguments() != null && inv.getArguments().length == 1)
return new RpcResult(inv.getArguments()[0]);
return invoker.invoke(inv);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
代码@1:实现com.alibaba.dubbo.rpc.Filter接口。
代码@2:添加Activate,其注解含义如下:
group: 所属组,String[],例如消费端、服务端。
value String[],如果指定该值,只有当消费者或服务提供者URL中包含属性名为value的键值对,该过滤器才处于激活状态。
before:String[],用于指定执行顺序,before指定的过滤器在该过滤器之前执行。
after:string[],用于指定执行顺序,after指定的过滤器在该过滤器之后执行。
order:用户指定顺序,值越小,越先执行。
除了支持默认的过滤器外,Dubbo还支持自定义Filter,可以通过service.filter指定过滤器,多个用英文逗号隔开,其配置方法为:
< dubbo:service ……>
< dubbo:parameter key = “service.filter” value = “filter1,filer2,…”/>
< /dubbo:service>
当然,可以为所有服务提供者设置共用过滤器,其指定方法为:
< dubbo:provider …>
< dubbo:parameter key = “service.filter” value = “filter1,filer2,…”/>
< /dubbo:provider>
消费端自定义过滤器的key为reference.filter,其使用方法在< dubbo:reference/>标签或< dubbo:consumer/>标签下定义属性。
关于自定义Filter的解析代码如下:
ExtensionLoader#getActivateExtension
public List<T> getActivateExtension(URL url, String key, String group) { // @1
String value = url.getParameter(key); // @2
return getActivateExtension(url, value == null || value.length() == 0 ? null : Constants.COMMA_SPLIT_PATTERN.split(value), group); // @3
}
1
2
3
4
代码@1:参数说明。
URL url:服务提供者或服务消费者url。
String key:过滤器属性key,服务提供者固定为:service.filter,服务消费者固定为reference.filter。
String group:服务提供者或服务消费者。
代码@2:从url中获取配置的自定义filter。
代码@3:如果value不为空,则将字符串调用split转换为数组,然后调用getActivateExtension方法,获取符合条件的过滤器。
ExtensionLoader#getActivateExtension
public List<T> getActivateExtension(URL url, String[] values, String group) {
List<T> exts = new ArrayList<T>();
List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values);
if (!names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { // @1
getExtensionClasses(); // @2
for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) {
String name = entry.getKey();
Activate activate = entry.getValue();
if (isMatchGroup(group, activate.group())) { // @3
T ext = getExtension(name);
if (!names.contains(name)
&& !names.contains(Constants.REMOVE_VALUE_PREFIX + name) // @4
&& isActive(activate, url)) { // @5
exts.add(ext);
}
}
}
Collections.sort(exts, ActivateComparator.COMPARATOR);
}
List<T> usrs = new ArrayList<T>();
for (int i = 0; i < names.size(); i++) { // @6
String name = names.get(i);
if (!name.startsWith(Constants.REMOVE_VALUE_PREFIX)
&& !names.contains(Constants.REMOVE_VALUE_PREFIX + name)) {
if (Constants.DEFAULT_KEY.equals(name)) {
if (!usrs.isEmpty()) {
exts.addAll(0, usrs);
usrs.clear();
}
} else {
T ext = getExtension(name);
usrs.add(ext);
}
}
}
if (!usrs.isEmpty()) {
exts.addAll(usrs);
}
return exts;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
代码@1:如果配置的service.filter或referecnce.filter包含了-default,表示禁用系统默认提供的一系列过滤器。
代码@2:如果不禁用系统默认过滤器链,则首先加载所有默认过滤器。
代码@3:根据group刷选出适配的过滤器。
代码@4:也可以对单个filter进行禁用,其方法是-过滤器名称的方式。例如如想禁用AccessLogFilter,则可以通过-accesslog方式禁用。-key,key为/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.r
pc.Filter中定义的key。
代码@5:判断过滤器是否激活,其逻辑是如果Filter上的@Activate注解value值不为空,则需要判断url中是否包含键为value的属性对,存在则启用,不存在则不启用。
代码@6:加载用户自定义的Filter,也即是service.filter或reference.filter指定的过滤器。
综上所述,Dubbo提供了过滤器机制,在真实服务被调用前提供扩展点。Filter机制就简单介绍到这里了,从下文开始会重点分析Dubbo服务提供的核心Filter。
如果需要自定过滤器,需要在自定的工程中META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter文件中注册。
本文就介绍到这里了,从下篇开始将会根据Dubbo的功能特性来详细分析其实现过程,其本质都是各种Dubbo 过滤器器。
————————————————
版权声明:本文为CSDN博主「唯有坚持不懈」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/prestigeding/article/details/82085705
Dubbo Filter机制概述的更多相关文章
- 基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪
原文链接:基于SLF4J的MDC机制和Dubbo的Filter机制,实现分布式系统的日志全链路追踪 一.日志系统 1.日志框架 在每个系统应用中,我们都会使用日志系统,主要是为了记录必要的信息和方便排 ...
- Android广播机制概述
1.Android广播机制概述 Android广播分为两个方面:广播发送者和广播接收者,通常情况下,BroadcastReceiver指的就是广播接收者(广播接收器).广播作为Android组件间的通 ...
- Dubbo SPI 机制源码分析(基于2.7.7)
Dubbo SPI 机制涉及到 @SPI.@Adaptive.@Activate 三个注解,ExtensionLoader 作为 Dubbo SPI 机制的核心负责加载和管理扩展点及其实现.本文以 E ...
- SQL Server 内存中OLTP内部机制概述(四)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...
- SQL Server 内存中OLTP内部机制概述(三)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...
- SQL Server 内存中OLTP内部机制概述(二)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...
- SQL Server 内存中OLTP内部机制概述(一)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...
- VS2010/MFC编程入门之五(MFC消息映射机制概述)
VS2010/MFC编程入门之五(MFC消息映射机制概述)-软件开发-鸡啄米 http://www.jizhuomi.com/software/147.html 上一讲鸡啄米为大家简单分析了MFC应用 ...
- JVM垃圾回收机制概述
JVM垃圾回收机制概述 1.定义 是指JVM用于释放那些不再使用的对象所占用的内存. 2.方式 2.1引用计数(早期) 当引用程序创建引用以及引用超出范围时,JVM必须适当增减引用数.当某个对象的引用 ...
随机推荐
- Django 中使用 MarkDown 插件
目录 Django 使用 markdown 插件 1 将 markdown 转化为 html 2 使用 markdown 编辑框 Django 使用 markdown 插件 Python-Markdo ...
- CSS3实现0.5px边框
用CSS设置边框宽度为0.5px,可以使边框看起来更加细腻,特别是在移动端,设计师会有这样的要求. 但遗憾的是,大多数Android手机并不能识别0.5px.因此我们可以使用CSS3来变通的实现0.5 ...
- SSM相关知识梳理面试
- Java8新特性。
常用函数接口: 函数式接口: 函数式接口在Java中是指:有且仅有一个抽象方法的接口(可以含其他方法). 而Java中的函数式编程的体现就是Lambda. @FunctionalInterface 注 ...
- Redis的内存分配
内存分配 Redis进程的内存消耗主要包括:自身内存 + 对象内存 + 缓冲内存 + 内存碎片.1 自身内存 Redis自身内存消耗非常少,通常used_memory在800KB左右,used_mem ...
- httprunner学习17-linux上安装httprunner环境
前言 如果你是在linux上安装httprunner环境,用的是python3的环境,安装成功后会发现hrun命令找不到,需添加软链接. 环境准备: centos 7.6 python 3.6 htt ...
- Reset.css和Normalize.css样式表初始化相关
(1)Reset.css 简介:在HTML标签在浏览器里有默认的样式,例如 p 标签有上下边距,strong标签有字体加粗样式,em标签有字体倾斜样式.不同浏览器的默认样式之间也会有差别,例如ul默认 ...
- windows + SQL Server环境,创建ArcSDE服务
ArcGIS for Server启用FeatureService需要ArcSDE和Geodatabase. 使用ArcSDE需要创建windows服务,ArcSDE只有命令行,所以只好阅读文档,找合 ...
- Ruby break, next, redo, retry
# -*- coding: UTF-8 -*- # E3.10-5.rb 演示break, next, redo, retry puts "演示break" c='a' for i ...
- [译] 在 UNIX 中,一切皆文件
原文地址:In UNIX Everything is a File 原文作者:ph7spot.com 译文出自:掘金翻译计划 本文永久链接:github.com/xitu/gold-m… 译者:pmw ...