基于ActiveMQ的统一日志服务

概述


以ActiveMQ + Log4j + Spring的技术组合,实现基于消息队列的统一日志服务。

与参考文章的比较

1. 更新了技术的版本
    e.g. Spring升级到4.2.0,ActiveMQ升级到5.13.2

2. 更新了依赖
    e.g. 使用activemq-client 5.13.2替换activemq-core最高版本是5.7.0,并取消了多余的spring-jms依赖

3. 精简了配置
    e.g. 去掉spring.xml中的jmsTemplate

4. 其他略述

前提

为理解文章的内容,你可能需要先了解下面的知识:

1. 了解基于Maven的项目结构

2. 下载并运行ActiveMQ

3. 了解log4j基于properties配置的简单用法

4. 了解基于Spring-webmvc的框架的搭建

当然,这只是建议......

技术版本

  1. ActiveMQ - 5.13.2
  2. Log4j - 1.2.17
  3. Spring - 4.2.4

结构图


1.节点拓扑图

说明:
  1. 应用系统基于log4j规范,通过JMSAppender将日志发送到ActiveMQ
  2. Log Server向ActiveMQ订阅消息,并指定MessageListener的实现来接收ActiveMQ发布的消息

实现


1.Log Server

你可以从 amqlog-server拿到源代码。

1.1.文件目录结构

复制代码
 1 pom.xml
 2 src/main/webapp/
 3     |---- WEB-INF/
 4               |---- web.xml  5 |---- index.jsp # 忽略  6 src/main/resources/  7 |---- spring-beans.xml  8 |---- topic.properties # 集中管理修改概率比较高的属性配置  9 src/main/java/ 10 |---- cn.sinobest.asj.logserver 11 |---- LogListener.java # 接收并输出log message
复制代码

1.2.文件内容

1.2.1. pom.xml
复制代码
 1 <project xmlns="http://maven.apache.org/POM/4.0.0"
 2  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  3  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">  4 <modelVersion>4.0.0</modelVersion>  5 <groupId>cn.sinobest.asj</groupId>  6 <artifactId>log-servler</artifactId>  7 <packaging>war</packaging>  8 <version>0.0.1-SNAPSHOT</version>  9 <name>amqlog-servler Maven Webapp</name> 10 <url>http://maven.apache.org</url> 11 <description>日志服务器,从ActiveMQ订阅主题,从而获取相关的日志数据</description> 12 <dependencies> 13 <dependency> 14 <groupId>junit</groupId> 15 <artifactId>junit</artifactId> 16 <version>3.8.1</version> 17 <scope>test</scope> 18 </dependency> 19 <!-- use to import spring-webmvc framework --> 20 <dependency> 21 <groupId>org.springframework</groupId> 22 <artifactId>spring-web</artifactId> 23 <version>4.2.4.RELEASE</version> 24 </dependency> 25 <dependency> 26 <groupId>org.springframework</groupId> 27 <artifactId>spring-jms</artifactId> 28 <version>4.2.4.RELEASE</version> 29 </dependency> 30 <!-- use to subscribe topic message from ActiveMQ --> 31 <dependency> 32 <groupId>org.apache.activemq</groupId> 33 <artifactId>activemq-client</artifactId> 34 <version>5.13.2</version> 35 </dependency> 36 <!-- use to extract log content from message --> 37 <dependency> 38 <groupId>log4j</groupId> 39 <artifactId>log4j</artifactId> 40 <version>1.2.17</version> 41 </dependency> 42 </dependencies> 43 <build> 44 <finalName>amqlog-servler</finalName> 45 </build> 46 </project>
复制代码
1.2.2. web.xml
复制代码
 1 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2  xmlns="http://java.sun.com/xml/ns/javaee"  3  xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  4  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  5  id="WebApp_ID" version="3.0" metadata-complete="false">  6 <display-name>Archetype Created Web Application</display-name>  7 <context-param>  8 <param-name>contextConfigLocation</param-name>  9 <param-value> 10  classpath:spring-beans.xml 11 </param-value> 12 </context-param> 13 <listener> 14 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 15 </listener> 16 </web-app>
复制代码
1.2.3. spring-beans.xml
装配图
说明:左上角标识由谁提供具体的实现,没有标识的有自己提供实现。
内容
复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"  3  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  4  xmlns:context="http://www.springframework.org/schema/context"  5  xsi:schemaLocation="http://www.springframework.org/schema/beans  6  http://www.springframework.org/schema/beans/spring-beans-4.2.xsd  7  http://www.springframework.org/schema/context  8  http://www.springframework.org/schema/context/spring-context-4.2.xsd">  9 <context:property-placeholder location="classpath:topic.properties" /> 10 <bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory"> 11 <property name="brokerURL" value="${topic.brokerURL}" /> 12 <!-- add trusted packages. see http://activemq.apache.org/objectmessage.html --> 13 <property name="trustedPackages"> 14 <list> 15 <value>org.apache.log4j.spi</value> 16 </list> 17 </property> 18 </bean> 19 <bean id="connectionFactory" 20  class="org.springframework.jms.connection.SingleConnectionFactory"> 21 <property name="targetConnectionFactory" ref="targetConnectionFactory" /> 22 </bean> 23 <bean id="destination" class="org.apache.activemq.command.ActiveMQTopic"> 24 <constructor-arg name="name" value="${topic.topicName}" /> 25 </bean> 26 <!-- define the message-listener to receive and dipose log data. --> 27 <bean id="messageListener" class="cn.sinobest.asj.logserver.LogListener" /> 28 <bean id="jmsContainer" 29  class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 30 <property name="connectionFactory" ref="connectionFactory" /> 31 <property name="destination" ref="destination" /> 32 <property name="messageListener" ref="messageListener" /> 33 </bean> 34 </beans>
复制代码
说明:
在targetConnectionFactory的属性中,指定了trustedPackages。ActiveMQ自5.12.2版本之后,强制用户指定一份可信任的packages白名单,以对付ObjectMessage存在的安全漏洞。具体内容可参考: http://activemq.apache.org/objectmessage.html
1.2.4. topic.properties
topic.brokerURL=tcp://localhost:61616
topic.topicName=demo
注意:brokerURL的值必须和ActiveMQ的监听地址一致。
1.2.5. LogListener.java
复制代码
 1 package cn.sinobest.asj.logserver;
 2 import javax.jms.JMSException;  3 import javax.jms.Message;  4 import javax.jms.MessageListener;  5 import org.apache.activemq.command.ActiveMQObjectMessage;  6 import org.apache.log4j.spi.LoggingEvent;  7 public class LogListener implements MessageListener {  8 private static final String TEMPLATE = "[%-5s] %s";  9 public void onMessage(Message message) { 10 try { 11 // extract LoggingEvent from message 12 // you must set org.apache.log4j.spi into the trusted packages list 13 // see spring-beans.xml in classpath 14 LoggingEvent event = (LoggingEvent) ((ActiveMQObjectMessage) message) 15  .getObject(); 16 String content = String.format(TEMPLATE, event.getLevel() 17  .toString(), event.getMessage().toString()); 18  System.out.println(content); 19 } catch (JMSException e) { 20  e.printStackTrace(); 21  } 22  } 23 }
复制代码
说明:这里的LoggingEvent来自package org.apache.log4j.spi,该package在spring-beans.xml的白名单中。

2.Log Client

log client模拟一般的应用系统。该应用系统有日志存储的需要,将日志发送给ActiveMQ而不用关心日志最终的存储方式。这里仅用一个简单的JavaSE project来模拟,但是已经足够提供完整的核心代码。
你可以从 amqlog-client拿到源代码。

2.1.文件目录结构

复制代码
1 pom.xml
2 src/main/resources/
3     |---- log4j.properties # 配置日志输出地点,及ActiveMQ的相关参数
4 |---- jndi.properties # 配置topic 5 src/main/java/ 6 |---- cn.sinobest.asj.logclient 7 |---- LogProducer.java # 生成并输出日志
复制代码

2.2.文件内容

2.2.1. pom.xml
复制代码
 1 <project xmlns="http://maven.apache.org/POM/4.0.0"
 2  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  3  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  4 <modelVersion>4.0.0</modelVersion>  5 <groupId>cn.sinobest.asj</groupId>  6 <artifactId>amqlog-client</artifactId>  7 <version>0.0.1-SNAPSHOT</version>  8 <name>Simple app to send log to ActiveMQ</name>  9 <description>模拟一般的应用系统,通过log4j发送日志到ActiveMQ</description> 10 <dependencies> 11 <!-- use to write log --> 12 <dependency> 13 <groupId>log4j</groupId> 14 <artifactId>log4j</artifactId> 15 <version>1.2.17</version> 16 </dependency> 17 <dependency> 18 <groupId>commons-logging</groupId> 19 <artifactId>commons-logging</artifactId> 20 <version>1.1.1</version> 21 </dependency> 22 <!-- use to import class org.apache.activemq.jndi.ActiveMQInitialContextFactory 23  to write log to ActiveMQ --> 24 <dependency> 25 <groupId>org.apache.activemq</groupId> 26 <artifactId>activemq-client</artifactId> 27 <version>5.13.2</version> 28 </dependency> 29 </dependencies> 30 </project>
复制代码
2.2.2. log4j.properties
复制代码
 1 # define the stand out appender
 2 log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 3 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  4 log4j.appender.stdout.layout.ConversionPattern=[%-5p] %-d{yyyy-MM-dd HH:mm:ss z}%n %m%n%n  5  6 # define the jms appender  7 log4j.appender.jms=org.apache.log4j.net.JMSAppender  8 log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory  9 log4j.appender.jms.ProviderURL=tcp://localhost:61616 10 # TopicBindingName可以自由配置,只需要确保提供对应的jndi属性即可 11 log4j.appender.jms.TopicBindingName=topicName 12 # TopicConnectionFactoryBindingName目前不能自由配置 13 log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory 14 15 # define the logger 16 log4j.rootLogger=INFO, stdout, jms
复制代码

注意:log4j.appender.jms.ProviderURL的值必须和ActiveMQ的监听地址一致。

2.2.3. jndi.properties
topic.topicName=demo
注意:key的后半部分(topicName)必须与log4j.properties中的log4j.appender.jms.TopicBindingName一致。
属性间的对应关系
2.2.4. LogProducer.java
复制代码
 1 package cn.sinobest.asj.logclient;
 2 import org.apache.commons.logging.Log;  3 import org.apache.commons.logging.LogFactory;  4 public class LogProducer {  5 private static final Log log = LogFactory.getLog(LogProducer.class);  6 /**  7  * @param args  8 */  9 public static void main(String[] args) { 10 log.debug("this is a debug message."); 11 log.info("this is a info message."); 12 log.warn("this is a warn message."); 13 log.error("this is a error message"); 14 System.exit(0); 15  } 16 }
复制代码
说明:debug的内容不会发送到ActiveMQ。

测试


    1. 启动ActiveMQ
      cd到ActiveMQ的解压缩目录,在cmd执行bin\activemq start
    2. 部署Log Server到Tomcat并启动
    3. 运行Log Client的LogProducer main方法
    4. Log Server的Console会有:

转载于:https://www.cnblogs.com/MarchThree/p/5299964.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值