Dubbo源码分析(AccessLogFilter)

954人阅读 评论(4) 收藏 举报
分类:

 

 上一篇博客简单的介绍了一下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);
	}

 

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:504986次
    • 积分:13116
    • 等级:
    • 排名:第1004名
    • 原创:290篇
    • 转载:5篇
    • 译文:1篇
    • 评论:3127条
    博客专栏