日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
使用Log4j、ActiveMQ和Spring實(shí)現(xiàn)異步日志

我的團(tuán)隊(duì)和我正在創(chuàng)建一個(gè)由一組RESTful JSON服務(wù)組成的服務(wù)平臺(tái),該平臺(tái)中的每個(gè)服務(wù)在平臺(tái)中的作用就是分別提供一些獨(dú)特的功能和/或數(shù)據(jù)。由于平臺(tái)中產(chǎn)生的日志四散各處,所以我們想,要是能將這些日志集中化處理一下,并提供一個(gè)能夠讓我們查看、過濾、排序和搜索我們所有的日志的基本型的日常查看工具就好了。我們還想讓我們的日志是異步式的,因?yàn)槲覀兛刹幌朐趯懭罩镜臅r(shí)候(比方說,可能會(huì)將日志直接寫入數(shù)據(jù)庫),讓我們提供的服務(wù)因?yàn)閷懭罩径鴷簳r(shí)被阻擋住。

創(chuàng)新互聯(lián)主營美蘭網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營網(wǎng)站建設(shè)方案,app軟件定制開發(fā),美蘭h5成都微信小程序搭建,美蘭網(wǎng)站營銷推廣歡迎美蘭等地區(qū)企業(yè)咨詢

實(shí)現(xiàn)這個(gè)目標(biāo)的策略非常簡單明了。

  1. 安裝ActiveMQ
  2. 創(chuàng)建一個(gè)log4j的日志追加器,將日志寫入隊(duì)列(log4j自帶了一個(gè)這樣的追加器,不過現(xiàn)在讓我們自己來寫一個(gè)吧。) 
  3. 寫一個(gè)消息偵聽器,從MQ服務(wù)器上所設(shè)置的JMS隊(duì)列中讀取日志并將日志持久化

下面讓我們分步來看這個(gè)策略是如何得以實(shí)現(xiàn)的。

安裝ActiveMQ

安裝一個(gè)外部的ActiveMQ服務(wù)器簡單極了。這個(gè)鏈接http://servicebus.blogspot.com/2011/02/installing-apache-active-mq-on-ubuntu.html是在Ubuntu上安裝ActiveMQ的一個(gè)非常棒的指南。你還可以選擇在你的應(yīng)用中嵌入一個(gè)消息代理,采用Spring就可以非常輕松實(shí)現(xiàn)。 我們將在后文中詳談具體的實(shí)現(xiàn)方法。

創(chuàng)建一個(gè)Lo4j的JMS日志追加器

首先,我們來創(chuàng)建一個(gè)log4j的JMS日志追加器。log4j自帶了一個(gè)這樣的追加器(該追加器沒有將日志寫入一個(gè)隊(duì)列,而是寫給了一個(gè)話題)

 
 
 
 
  1. import javax.jms.DeliveryMode;  
  2. import javax.jms.Destination;  
  3. import javax.jms.MessageProducer;  
  4. import javax.jms.ObjectMessage;  
  5. import javax.jms.Session;  
  6.  
  7. import org.apache.activemq.ActiveMQConnectionFactory;  
  8. import org.apache.log4j.Appender;  
  9. import org.apache.log4j.AppenderSkeleton;  
  10. import org.apache.log4j.Logger;  
  11. import org.apache.log4j.PatternLayout;  
  12. import org.apache.log4j.spi.LoggingEvent;  
  13.  
  14. /**  
  15.  * JMSQueue appender is a log4j appender that writes LoggingEvent to a queue.  
  16.  * @author faheem  
  17.  *  
  18.  */ 
  19. public class JMSQueueAppender extends AppenderSkeleton implements Appender{  
  20.  
  21. private static Logger logger = Logger.getLogger("JMSQueueAppender");  
  22.  
  23. private String brokerUri;  
  24. private String queueName;  
  25.  
  26. @Override 
  27. public void close() {  
  28.  
  29. }  
  30.  
  31. @Override 
  32. public boolean requiresLayout() {  
  33.     return false;  
  34. }  
  35.  
  36. @Override 
  37. protected synchronized void append(LoggingEvent event) {  
  38.  
  39.    try {  
  40.  
  41.      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(  
  42.                     this.brokerUri);  
  43.  
  44.      // Create a Connection  
  45.      javax.jms.Connection connection = connectionFactory.createConnection();  
  46.      connection.start();np  
  47.  
  48.      // Create a Session  
  49.      Session session = connection.createSession(false,Session.AUTO_ACKNOWLEDGE);  
  50.  
  51.      // Create the destination (Topic or Queue)  
  52.      Destination destination = session.createQueue(this.queueName);  
  53.  
  54.      // Create a MessageProducer from the Session to the Topic or Queue  
  55.      MessageProducer producer = session.createProducer(destination);  
  56.      producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);  
  57.  
  58.      ObjectMessage message = session.createObjectMessage(new LoggingEventWrapper(event));  
  59.  
  60.      // Tell the producer to send the message  
  61.      producer.send(message);  
  62.  
  63.      // Clean up  
  64.      session.close();  
  65.      connection.close();  
  66.   } catch (Exception e) {  
  67.      e.printStackTrace();  
  68.   }  
  69. }  
  70.  
  71. public void setBrokerUri(String brokerUri) {  
  72.     this.brokerUri = brokerUri;  
  73. }  
  74.  
  75. public String getBrokerUri() {  
  76.     return brokerUri;  
  77. }  
  78.  
  79. public void setQueueName(String queueName) {  
  80.     this.queueName = queueName;  
  81. }  
  82.  
  83. public String getQueueName() {  
  84.     return queueName;  
  85. }  

第37行: log4j將一個(gè)LoggingEvent對(duì)象作為參數(shù)對(duì)append方法進(jìn)行調(diào)用,這個(gè)LoggingEvent對(duì)象表示了對(duì)logger的一次調(diào)用,它封裝了每一個(gè)日志項(xiàng)的所有信息。

第41和42行:將指向JMS的uri作為參數(shù),創(chuàng)建一個(gè)連接工廠對(duì)象,在我們的情況下,該uri指向的是我們的ActiveMQ服務(wù)器。

第45, 46和49行: 我們同JMS服務(wù)器建立一個(gè)連接和會(huì)話。會(huì)話有多種打開模式。在Auto_Acknowledge模式的會(huì)話中,消息的應(yīng)答會(huì)自動(dòng)發(fā)生。Client_Acknowledge 模式下,客戶端需要對(duì)消息的接收和/或處理進(jìn)行顯式地應(yīng)答。另外還有兩種其它的模式。有關(guān)細(xì)節(jié),請(qǐng)參考文檔http://download.oracle.com/javaee/1.4/api/javax/jms/Session.html

第52行: 創(chuàng)建一個(gè)隊(duì)列。將隊(duì)列的名字作為參數(shù)發(fā)送給連接

下面讓我們看看這里面發(fā)生了什么事情。

第19行:We我們實(shí)現(xiàn)了的Log4J日志追加器接口,該接口要求我們實(shí)現(xiàn)三個(gè)方法:requiresLayout, closeappend。我們將暫時(shí)簡化處理過程,實(shí)現(xiàn)所需的append方法。在對(duì)logger進(jìn)行調(diào)用時(shí)這個(gè)方法就會(huì)被調(diào)用。

第56行: 我們將發(fā)送模式設(shè)置為Non_Persistent。另一個(gè)可選的模式是Persistent ,在這種模式下,消息會(huì)持久化到一個(gè)持久性存儲(chǔ)系統(tǒng)中。持久化模式會(huì)降低系統(tǒng)速度,但能增加了消息傳遞的可靠性。

第58行: 這行我們做了很多事。首先我將一個(gè)LoggingEvent對(duì)象封裝到了一個(gè)LoggingEventWrapper對(duì)象之中。這么做是因?yàn)?em>LoggingEvent對(duì)象有一些屬性不支持序列化,另外還有一個(gè)原因是我想記錄一些額外的信息,比如IP地址和主機(jī)名。接下來,使用JMS的會(huì)話對(duì)象,我們把一個(gè)對(duì)象(LoggingEventWrapper對(duì)象)做好了發(fā)送前的準(zhǔn)備。

第61行: 我將該對(duì)象發(fā)送到了隊(duì)列中。

下面所示是LoggingEventWrapper的代碼。

 
 
 
 
  1. import java.io.Serializable;  
  2. import java.net.InetAddress;  
  3. import java.net.UnknownHostException;  
  4.  
  5. import org.apache.log4j.EnhancedPatternLayout;  
  6. import org.apache.log4j.spi.LoggingEvent;  
  7.  
  8. /**  
  9.  * Logging Event Wraps a log4j LoggingEvent object. Wrapping is required by some information is lost  
  10.  * when the LoggingEvent is serialized. The idea is to extract all information required from the LoggingEvent  
  11.  * object, place it in the wrapper and then serialize the LoggingEventWrapper. This way all required data remains  
  12.  * available to us.  
  13.  * @author faheem  
  14.  *  
  15.  */ 
  16.  
  17. public class LoggingEventWrapper implements Serializable{  
  18.  
  19.     private static final String ENHANCED_PATTERN_LAYOUT = "%throwable";  
  20.     private static final long serialVersionUID = 3281981073249085474L;  
  21.     private LoggingEvent loggingEvent;  
  22.  
  23.     private Long timeStamp;  
  24.     private String level;  
  25.     private String logger;  
  26.     private String message;  
  27.     private String detail;  
  28.     private String ipAddress;  
  29.     private String hostName;  
  30.  
  31.     public LoggingEventWrapper(LoggingEvent loggingEvent){  
  32.         this.loggingEvent = loggingEvent;  
  33.  
  34.         //Format event and set detail field  
  35.         EnhancedPatternLayout layout = new EnhancedPatternLayout();  
  36.         layout.setConversionPattern(ENHANCED_PATTERN_LAYOUT);  
  37.         this.detail = layout.format(this.loggingEvent);  
  38.     }  
  39.  
  40.     public Long getTimeStamp() {  
  41.         return this.loggingEvent.timeStamp;  
  42.     }  
  43.  
  44.     public String getLevel() {  
  45.         return this.loggingEvent.getLevel().toString();  
  46.     }  
  47.  
  48.     public String getLogger() {  
  49.         return this.loggingEvent.getLoggerName();  
  50.     }  
  51.  
  52.     public String getMessage() {  
  53.         return this.loggingEvent.getRenderedMessage();  
  54.     }  
  55.  
  56.     public String getDetail() {  
  57.         return this.detail;  
  58.     }  
  59.  
  60.     public LoggingEvent getLoggingEvent() {  
  61.         return loggingEvent;  
  62.     }  
  63.  
  64.     public String getIpAddress() {  
  65.         try {  
  66.             return InetAddress.getLocalHost().getHostAddress();  
  67.         } catch (UnknownHostException e) {  
  68.             return "Could not determine IP";  
  69.         }  
  70.     }  
  71.  
  72.     public String getHostName() {  
  73.         try {  
  74.             return InetAddress.getLocalHost().getHostName();  
  75.         } catch (UnknownHostException e) {  
  76.             return "Could not determine Host Name";  
  77.         }  
  78.     }  

#p#

消息偵聽器

消息偵聽器會(huì)對(duì)隊(duì)列(或話題)進(jìn)行“偵聽”。一旦有新消息添加到了隊(duì)列中,onMessage 方法就會(huì)得到調(diào)用。

 
 
 
 
  1. import javax.jms.JMSException;  
  2. import javax.jms.Message;  
  3. import javax.jms.MessageListener;  
  4. import javax.jms.ObjectMessage;  
  5.  
  6. import org.apache.log4j.Logger;  
  7. import org.springframework.beans.factory.annotation.Autowired;  
  8. import org.springframework.stereotype.Component;  
  9.  
  10. @Component 
  11. public class LogQueueListener implements MessageListener  
  12. {  
  13.     public static Logger logger = Logger.getLogger(LogQueueListener.class);  
  14.  
  15.     @Autowired 
  16.     private ILoggingService loggingService;  
  17.  
  18.     public void onMessage( final Message message )  
  19.     {  
  20.         if ( message instanceof ObjectMessage )  
  21.         {  
  22.             try{  
  23.                 final LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper)((ObjectMessage) message).getObject();  
  24.                 loggingService.saveLog(loggingEventWrapper);  
  25.             }  
  26.             catch (final JMSException e)  
  27.             {  
  28.                 logger.error(e.getMessage(), e);  
  29.             } catch (Exception e) {  
  30.             logger.error(e.getMessage(),e);  
  31.         }  
  32.         }  
  33.     }  

第23行: 檢查從隊(duì)列中拿到的對(duì)象是否是ObjectMessage的實(shí)例

第26行: 從消息中提取出LoggingEventWrapper對(duì)象

第27行: 調(diào)用服務(wù)方法將日志持久化

Spring配置

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.      
  12.      
  13.      
  14.  
  15.  
  16.  
  17.      
  18.  
  19.  
  20.  
  21.      
  22.  
  23.  

第5到9行: 使用代理標(biāo)簽建立一個(gè)嵌入式消息代理。既然我用的是外部消息代理,所以我就不需要它了。

第12行: 給出你想要連接的隊(duì)列的名字

第14行: 代理服務(wù)器的URI

15到19行: 連接工廠的設(shè)置

26到28行: 消息偵聽器的設(shè)置,這里可以指定用于從隊(duì)列中讀取消息的并發(fā)現(xiàn)線程的個(gè)數(shù)

當(dāng)然,上面的例子做不到讓你能夠拿來就用。你還需要包含所有的JMS依賴庫并實(shí)現(xiàn)完成日志持久化任務(wù)的服務(wù)。但是,我希望本文能夠?yàn)槟闾峁┮粋€(gè)相當(dāng)不錯(cuò)的思路。

英文原文:Asynchronous logging using Log4j, ActiveMQ and Spring

譯文鏈接:http://www.oschina.net/translate/asynchronous-logging-using-log4j-activemq-and-spring


當(dāng)前題目:使用Log4j、ActiveMQ和Spring實(shí)現(xiàn)異步日志
路徑分享:http://m.5511xx.com/article/djppegd.html