需求
上层业务系统在调用底层的服务的时候,底层系统需要记录全部的入参、出参和处理耗时。
设计
Dubbo的Filter机制,是专门为服务提供方和服务消费方调用过程进行拦截设计的,每次远程方法执行,该拦截都会被执行。这样就为开发者提供了非常方便的扩展性,比如为dubbo接口实现ip白名单功能、监控功能等等。
自定义FIlter实现方法很简单,分为3个步骤:
1、自定义Filter,必须继承com.alibaba.dubbo.rpc.Filter接口
2、在resources目录下添加纯文本文件META-INF/dubbo/com.alibaba.dubbo.rpc.Filter,内容写成 xxx=xxx.xxx.xxxFilter
3、在dubbo配置xml中添加 <dubbo:provider filter="xxxFilter" /> 或者 <dubbo:consumer filter="xxxFilter" /> 使Filter生效。
代码实现
自定义Filter实现
package com.udf.dubbo;
import java.util.Arrays;
import org.apache.log4j.Logger;
import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
@Activate(group = Constants.PROVIDER, order = -999)
public class MonitorServiceFilter implements Filter {
private static Logger log = Logger.getLogger("MonitorService");
private static Logger msgLogger = Logger.getLogger("Message");
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation)
throws RpcException {
// TODO Auto-generated method stub
Result result = null;
msgLogger.info("IP:" + RpcContext.getContext().getRemoteHost()
+ ", Service:" + invoker.getInterface().getName()
+ ", Method:" + invocation.getMethodName()
+ ", Request:{" + Arrays.toString(invocation.getArguments())
+ "}."
);
Long startTime = System.currentTimeMillis();
try {
result = invoker.invoke(invocation);
if (result.getException() instanceof Exception) {
throw new Exception(result.getException());
}
} catch (Exception e) {
log.error("IP:" + RpcContext.getContext().getRemoteHost()
+ ", Service:" + invoker.getInterface().getName()
+ ", Method:" + invocation.getMethodName()
+ ", Exception:{" + e.toString() + "}.");
} finally {
msgLogger.info("IP:" + RpcContext.getContext().getRemoteHost()
+ ", Service:" + invoker.getInterface().getName()
+ ", Method:" + invocation.getMethodName()
+ ", Response:{" + result.toString()
+ "}."
);
log.info("IP:" + RpcContext.getContext().getRemoteHost()
+ ", Service:" + invoker.getInterface().getName()
+ ", Method:" + invocation.getMethodName()
+ ", consume: " + (System.currentTimeMillis()-startTime) + " ms."
);
}
return result;
}
}
Filter配置
在服务提供者配置Filter
验证
经验
1、配置Filter,并将com.alibaba.dubbo.rpc.Filter文件打包到jar包中;
2、服务端如何加载Filter
3、不同业务场景下调用Filter日志输出信息,(1)业务正常响应日志正常输出,(2)服务调用超时,Filter日志正常输出,消费者收到超时异常,不会收到响应信息,(3)服务调用线程池满时,Filter收不到服务调用,消费者收到线程池满异常