Dubbo 过滤器简单使用
通过过滤器我们可以对请求进行统一处理,比如请求链路id 生成 ,参数验证等等。 Dubbo中过滤器分服务端和消费端,通过group 指定,比如下面例子就是服务消费端过滤器例子。
本文主要内容
-
通过参数校验例子,展示过滤器使用。
-
过滤器源码简单分析
@Activate(group = CONSUMER, order = -10000)
public class CustomerTokenFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String token = RpcUtil.getSign("1234567");
RpcContext.getContext().getObjectAttachments().put("accessToken",token);
return invoker.invoke(invocation);
}
}
使用过滤器对请求校验
本文给的例子 校验流程:
-
消费端:将请求所有参数 按顺序拼接成字符串,最后拼接上消费端密钥,计算出md5; 并通过隐藏参数传递。
-
服务端:将请求所有参数 按顺序拼接成字符串,最后拼接上服务端密钥,计算出md5; 如果服务端计算出md5值 与 消费端传来的md5值一致 说明 消费端密钥与服务端密钥一致。 则请求合法,否则报错。
服务端过滤器代码
假设服务端与消费端约定的秘钥是123456;
@Activate(group = PROVIDER, order = -10000)
public class CustomerTokenValidFilter implements Filter {
private String ak = "123456";
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String token = RpcContext.getContext().getAttachment("accessToken");
String expireToken = RpcUtil.getSign(ak);
if(!expireToken.equals(token)){
throw new RuntimeException("参数检验失败,请求不合法");
}
return invoker.invoke(invocation);
}
}
服务端过滤器配置
<dubbo:service interface="com.codetonight.service.HelloService" ref="helloServiceImpl" retries="0" filter="customertokenvalidfilter" >
</dubbo:service>
消费端过滤器
@Activate(group = CONSUMER, order = -10000)
public class CustomerTokenFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String token = RpcUtil.getSign("1234567");
RpcContext.getContext().getObjectAttachments().put("accessToken",token);
return invoker.invoke(invocation);
}
}
消费端过滤器配置
<dubbo:reference id="helloService" interface="com.codetonight.service.HelloService" filter="customertokenfilter">
</dubbo:reference>
过滤器相关部分源码
我们看看这个类 ProtocolFilterWrapper
看过之前文章Dubbo SPI 使用总结就很容易理解, ProtocolFilterWrapper
对Protocol 进行 AOP 增强。
-
export方法 里调用
buildInvokerChain
构建filter 责任链实现服务端过滤器够级 -
refer 方法同样调用
buildInvokerChain
构建filter 责任链实现消费端过滤器够级
过滤器也是SPI接口,服务端加载group是provider,消费端加载的是consumer。
最终责任链末端就是需要执行业务的invoker。
内置的过滤器
echo=org.apache.dubbo.rpc.filter.EchoFilter
generic=org.apache.dubbo.rpc.filter.GenericFilter
genericimpl=org.apache.dubbo.rpc.filter.GenericImplFilter
token=org.apache.dubbo.rpc.filter.TokenFilter
accesslog=org.apache.dubbo.rpc.filter.AccessLogFilter
activelimit=org.apache.dubbo.rpc.filter.ActiveLimitFilter
classloader=org.apache.dubbo.rpc.filter.ClassLoaderFilter
context=org.apache.dubbo.rpc.filter.ContextFilter
consumercontext=org.apache.dubbo.rpc.filter.ConsumerContextFilter
exception=org.apache.dubbo.rpc.filter.ExceptionFilter
executelimit=org.apache.dubbo.rpc.filter.ExecuteLimitFilter
deprecated=org.apache.dubbo.rpc.filter.DeprecatedFilter
compatible=org.apache.dubbo.rpc.filter.CompatibleFilter
timeout=org.apache.dubbo.rpc.filter.TimeoutFilter
tps=org.apache.dubbo.rpc.filter.TpsLimitFilter
总结
过滤器适用于一些全局统一的处理,比如参数校验、权限控制、统一异常处理等等。