zoukankan      html  css  js  c++  java
  • 基于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执行binactivemq start
      2. 部署Log Server到Tomcat并启动
      3. 运行Log Client的LogProducer main方法
      4. Log Server的Console会有:
  • 相关阅读:
    crm-ssh-列表显示(顾客列表,用户,联系人列表)
    leetcode- Rotate Array 旋转数组
    ssh的整合
    svn详解和使用
    leetcode-Plus One 加一
    spring-jdbc-aop事务
    leetcode-Remove Duplicates from Sorted Array
    0020 DRF框架开发(07 基类视图 GenericAPIView)
    0019 DRF框架开发(06 基类视图 APIView)
    0018 DRF框架开发(05 序列化器的字段与选项)
  • 原文地址:https://www.cnblogs.com/MarchThree/p/5299964.html
Copyright © 2011-2022 走看看