在用dubbo提供的便捷时,也会带来诸多的不便,服务多了,问题排查的难度就会增加,服务间调用日志,可以帮我们解决部分问题。
那dubbo怎么去增加服务间调用的日志呢?
1.在resources资源目录下的META-INF文件夹下,新建dubbo目录,增加名为com.alibaba.dubbo.rpc.Filter的配置文件
配置文件的内容如下:
logFilter=com.find.job.service.boot.filter.LogFilter
com.find.job.service.boot.filter.LogFilter是我们自定义的日志拦截器全类名。
2.编写我们的日志拦截器
package com.find.job.service.boot.filter;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import com.find.job.common.util.JsonUtil;
public class LogFilter implements Filter {
private static Logger logger = LoggerFactory.getLogger(LogFilter.class);
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
HashMap<String, Object> logContent = new HashMap<>();
logContent.put("args", invocation.getArguments());
logContent.put("methodName", invocation.getMethodName());
logContent.put("client", RpcContext.getContext().getRemoteAddressString());
logContent.put("host", RpcContext.getContext().getLocalAddressString());
Result result = null;
try {
long start = System.currentTimeMillis();
result = invoker.invoke(invocation);
long end = System.currentTimeMillis();
logContent.put("elapsedtime", end - start);
if (result.getException() != null) {
logContent.put("exception", result.getException());
logger.error("remote throw an exception, request url is {},param is {}.",
invoker.getUrl().getAbsolutePath(), JsonUtil.objectToJSON(logContent));
} else {
logger.info("remote request url is {},param is {}.", invoker.getUrl().getAbsolutePath(),
JsonUtil.objectToJSON(logContent));
}
} catch (Exception ex) {
logger.error("remote throw an exception, request url is {},param is {}.", invoker.getUrl().getAddress(),
ex.getCause());
throw ex;
}
return result;
}
}
3.在我们的服务中设置filter
private void setConfig(ServiceBean<?> serviceConfig, Class<?> c) {
serviceConfig.setApplication(applicationConfig());
serviceConfig.setRegistry(registryConfig());
serviceConfig.setProtocol(protocolConfig());
serviceConfig.setInterface(c);
// serviceConfig.setGroup("Group");接口多实现指定分组
// serviceConfig.setMerger(merger);分组多实现接口聚合
// serviceConfig.setStub(false);本地存根
// serviceConfig.setDelay(30000);30秒后暴露,设置为-1时表示spring初始化完成再暴露服务
// serviceConfig.setLoadbalance("leastactive");调用并发数最小的 Provider(Consumer端并发数)
serviceConfig.setExecutes(100);// 100为最大并发数
serviceConfig.setActives(100);// 100为【客服端】最大并发数
// see:com.find.job.service.boot.filter.LogFilter自定义过滤器,拦截用户请求信息
serviceConfig.setFilter("logFilter");
serviceConfig.setRetries(2);
}
OK,就这三步,我们就可以服务间的调用日志了,包括方法名和参数列表。
日志中,记录了调用的地址,参数列表,接口调用时长。
时长在监控服务调用链时很重要哦,另外可以加一些其他的参数,将整个调用链串联起来,做服务的性能检测。