您的位置:首页 > 其它

Dubbo源码分析(AccessLogFilter)

2016-09-01 08:57 190 查看
 
 上一篇博客简单的介绍了一下Dubbo中的Filter,下面几篇博客来找其中的几个filter来分析一下。

 首先来看一下Filter接口

 public interface Filter {
Result invoke(Invoker<?> invoker,Invocation invocation) throws RpcException;
} 就一个方法,用来作为Invoker的代理,其中Invocation封装了所需要的参数信息等。

 
 AccessLogFilter实现类
 该类用来记录,每一次调用的信息,格式如下所示
 


 如果要用该filter的话,需要在提供方中配置以下信息,如果不配置的话,日志会打到类似
  dubbo.accesslog.interfacename的文件中

 


  

 AccessLogFilter源码分析
 在LogFilter的内部维护了一个map结构,key为日志的名称,value是一个set集合,维护了日志的每一次调用的详细信息。内部通过一个线程,隔一段时间都会把日志给输出出去。代码如下所示
 private final ConcurrentMap<String, Set<String>> logQueue = new ConcurrentHashMap<String, Set<String>>();

private final ScheduledExecutorService logSchedule = Executors
.newScheduledThreadPool(2, new NamedThreadFactory(
"Dubbo-Access-Log", true));

private volatile ScheduledFuture<?> logFuture = null;

private class LogTask implements Runnable {
public void run() {
try {
if (logQueue != null && logQueue.size() > 0) {
for (Map.Entry<String, Set<String>> entry : logQueue
.entrySet()) {
try {

//..创建目录
//..并对日期做判断,第二题的日志会以日期结尾
FileWriter writer = new FileWriter(file, true);
try {
for (String msg : logSet) {
writer.write(msg);
writer.write("\r\n");
}
writer.flush();
} finally {
writer.close();
}
logSet.clear();
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}

private void init() {
if (logFuture == null) {
synchronized (logSchedule) {
// 这个判断保证了只初始化一次
//需要加锁,防止并发
if (logFuture == null) {
logFuture = logSchedule.scheduleWithFixedDelay(
new LogTask(), LOG_OUTPUT_INTERVAL,
LOG_OUTPUT_INTERVAL, TimeUnit.MILLISECONDS);
}
}
}
}

/* log输出日志操作 */
private void log(String accesslog, String logmessage) {
init();
Set<String> logSet = logQueue.get(accesslog);
if (logSet == null) {
logQueue.putIfAbsent(accesslog, new ConcurrentHashSet<String>());
logSet = logQueue.get(accesslog);
}

if (logSet.size() < LOG_MAX_BUFFER) {
logSet.add(logmessage);
}
}

public Result invoke(Invoker<?> invoker, Invocation inv)
throws RpcException {

try {

//。。。。拼接日志信息操作
if (ConfigUtils.isDefault(accesslog)) {
//没有设置的话,会以默认形式进行
LoggerFactory.getLogger(
ACCESS_LOG_KEY + "."
+ invoker.getInterface().getName()).info(
msg);
} else {
//每次调用前都会输出日志
log(accesslog, msg);
}
}
} catch (Throwable t) {
logger.warn("Exception in AcessLogFilter of service(" + invoker
+ " -> " + inv + ")", t);
}
return invoker.invoke(inv);
}


 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: