天天看點

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

随着項目的逐漸擴大,日志的增加也變得更快。log4j是常用的日志記錄工具,在有些時候,我們可能需要将log4j的日志發送到專門用于記錄日志的遠端伺服器,特别是對于稍微大一點的應用。這麼做的優點有:

遠端列印日志的原理:項目a需要列印日志,而a調用log4j來列印日志,log4j的jmsappender又給配置的位址(activemq位址)發送一條jms消息,此時綁定在queue上的項目b的監聽器發現有消息到來,于是立即喚醒監聽器的方法開始輸出日志。

本文将使用兩個java項目product和logging,其中product項目就是模拟線上的項目,而logging項目模拟運作在專用的日志伺服器上的項目。說明:本文的例子是在windows平台下。

解壓後不需要任何配置,進入到bin下對應的系統架構檔案夾

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

輕按兩下activemq.bat啟動,如果看到類似下面的頁面,就代表activemq啟動好了:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析
Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

可以點選manage activemq broker進入queue的檢視界面。

我用maven來管理項目,友善維護各種依賴的jar包。先看下項目結構:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

項目不複雜,主要是4個檔案:pom.xml,main.java,log4j.properties和jndi.properties

pom.xml中主要是聲明項目的依賴包,其餘沒有什麼東西了:

main.java:

說明:然後是log4j.properties:

其實按理說隻需要這麼三個檔案就可以了,但是這時候執行會報錯:

為什麼會報錯呢?來看看jmsappender的javadoc文檔,它是這麼描述的:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

大意是說,jmsappender需要一個jndi配置來初始化一個jndi上下文(context)。因為有了這個上下文才能管理jms topic和topic的連接配接。于是為項目配置一個叫jndi.properties的檔案,其内容為:

然後再運作就不會報錯了。我們先來看看activemq(注意切換到topic标簽頁下):

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

可以看到,主題為logtopic的消息,有3條進queue,這3條也出queue了。而出queue的消息,已經被我們的監聽器收到并列印出來了:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

需要注意的是,本例隻是一個很簡單的例子,目的是闡明遠端列印日志的原理。實際項目中,一般日志伺服器上運作着的,不是項目,而是專用的日志記錄器。下面,我們就把這個項目拆分成兩個項目,并用spring來管理這些用到的bean

修改後的product的項目結構并沒有改變,改變的隻是main類:

這個main類和普通的logger調用一樣,僅僅負責列印日志。有沒有覺得太簡單了呢?

來看看項目結構圖:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

為了讓監聽器一直活着,我把logging寫成了一個web項目,跑在tomcat上。index.jsp就是個hello world字元串而已,用來驗證logging活着。注意,在logging項目中,已沒有product項目中的log4j.properties和jndi.properties兩個檔案。

來看看另外幾個檔案:

pom.xml(每個包的目的都寫在注釋裡了):

web.xml

spring.xml

logmessagelistener指向我們自己實作的日志消息處理邏輯類,topicdestination則關注topic為“logtopic”的消息,而jmscontainer把這兩個對象綁在一起,這樣就能接收并處理消息了。

最後就是偉大的監聽器了logmessagelistener了:

哈哈,說偉大,其實太簡單了。但是可以看到,監聽器裡面就是之前product項目中main類裡面移除的實作了messagelistener接口中的代碼。

在執行測試前,删掉activemq中所有的queue,確定測試效果。

先運作logging項目,開始queue的監聽。再運作product的main類的main函數,可以先看到main類列印到控制台的日志:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

接下來去看看queue中的情況:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

可以看到有個叫logtopic的主題的消息,進了3條,出了3條。不用想,出queue的3條日志已經被logging項目的listener接收并列印出來了,現在去看看tomcat的控制台:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

還要注意queue中的logtopic的consumer數量為1而不是0,這與開始的截圖不同。我們都知道這個consumer是logging項目中的logmessagelistener對象,它一直活着,是因為tomcat一直活着;之前的consumer數量為0,是因為在main函數執行完後,queue的監聽器(也是寫日志的對象)就退出了。

通過把product和logging項目分别放在不同的機器上執行,在第三台機器上部署activemq(當然你可以把activemq搭建在任意可以通路的地方),再配置一下product項目的log4j.properties檔案和logging項目的spring.xml檔案就能用于生産環境啦。

jmsappender類将loggingevent執行個體序列化成objectmessage,并将其發送到jms server的一個指定topic中,是以,使用此種将日志發送到遠端的方式隻支援topic方式發送,不支援queue方式發送。我們再log4j.properties中配置了這一句:

這一句指定了使用的appender,打開這個appender,在裡面可以看到很多setter,比如:

Spring+Log4j+ActiveMQ實作遠端記錄日志——實戰+分析

這些setter不是巧合,而正是對應了我們在log4j.properties中設定的其他幾個選項:

來看看jmsappender的activeoptions方法,這個方法是用于使我們在log4j.properties中的配置生效的:

上面初始化了一個topicconnection,一個topicsession,一個topicpublisher。咱們再來看看這個appender的append方法:

這裡使用topicpublisher.publish()方法,把序列化的消息釋出出去。可見這也證明了jmsappender隻支援以topic方式發送消息。

樣例下載下傳:百度網盤

參考:

<a href="http://activemq.apache.org/how-do-i-use-log4j-jms-appender-with-activemq.html">http://activemq.apache.org/how-do-i-use-log4j-jms-appender-with-activemq.html</a>