JMS+activeMq+spring簡單學習及模擬處理新聞日誌場景
在介紹JMS的知識之前,先說說我瞭解學習JMS的原因。 公司有一個新聞專案,我們知道新聞網站都是面向所有使用者群的,它不但要求新聞的實時性,還要求網頁的響應時間必須很快, 你想啊,如果你在某個網站看新聞,如果網頁響應比較慢,那誰願意來你網站看新聞啊,所以新聞網站的網頁都進行靜態化、新聞 頁所需資料都放在快取系統(比如memcache之類)等等一些處理,也就是說使用者請求訪問某個頁面時,伺服器要儘可能快響應,這就 要求我們後臺,不能像一些企業應用系統(比如人事管理系統之類)那樣,每個請求所需的資料都從資料庫查詢,並且不止查詢 一次。因為這些應用系統都是有特定的使用人群的,併發量不大,所以哪怕不停查詢資料庫,響應也夠快,使用者也能接受。新聞 這專案,現在有個需求,需要收集記錄使用者的訪問日誌,比如使用者訪問了哪些新聞頻道列表,訪問了哪些新聞詳情等等,為統計 系統提供資料。這樣問題來了,網頁請求,連資料庫查詢都儘量避免,更別說執行日誌寫操作,要知道往資料庫裡面插資料,如 果表的資料量很大了,並且又有索引,那插入一條新資料所需的時間就很大的,如果併發量高時,還有可能阻塞,這就嚴重影響 網頁請求的響應速度了。有些小夥伴就說了,那我新啟動一個執行緒單獨對日誌寫不就行了嗎?對,這是一種方法,但是我們要注 意,如果請求非常多,那新建立的執行緒就會非常多,會嚴重影響伺服器的效能的。看了下 專案程式碼,專案中採用的是利用JMS來做。 |
一看上面的圖,這不是生產者和消費者模式嗎?是的,沒錯。看上面圖,可以看出,新聞應用伺服器、mq伺服器、日誌處理 伺服器都是分開的,新聞應用伺服器只需要把日誌資料傳送到mq伺服器就行了,至於日誌資料是怎樣處理的,插入資料庫的速度 如何,是否成功等,新聞應用伺服器不必關心,這樣一來就能儘可能快的提高使用者的請求響應了。 好了,接下來,我們學習瞭解一下關於JMS的一些基礎知識。 |
下載安裝執行activeMq網路上下載一個activeMq,然後執行它 可以看到,預設的連線地址和埠是tcp://127.0.0.1:61616,同時還可以通過瀏覽器訪問http://localhost:8161/來檢視activeMq裡 面佇列等一些基礎資料資訊。現在瀏覽器開啟http://localhost:8161/ 我們選擇Queue Views下的XML來看下 可以看到你佇列名稱,以及一些狀態資料 |
JMS基本概念JMS(Java Message Service) 即Java訊息服務。它提供標準的產生、傳送、接收訊息的介面簡化企業應用的開發。它支援兩種訊息通訊模型: 點到點(point-to-point)(P2P)模型和釋出/訂閱(Pub/Sub)模型。P2P 模型規定了一個訊息只能有一個接收者;Pub/Sub 模型允許一個
訊息可以有多個接收者。
這個訊息被一個接收者讀取之後,它就在這個Queue中消失了,所以一個訊息只能被一個接收者消費。 在監聽,當一個訊息到達這個Topic之後,所有訊息接收者都會收到這個訊息。 簡單的講,點到點模型和釋出/訂閱模型的區別就是前者是一對一,後者是一對多。 Queue的簡單例子1現在我們來看個簡單例子,用來模擬上面的新聞應用伺服器、activeMq、日誌處理伺服器這三方過程.首先啟 動activeMq服務,然後建立一個專案jms_produce用來生產資料,jms_consumer用來消費資料 其中jms_produce的MessageSend.java的程式碼如下
jms_consumer中的MessageRecieve.java程式碼如下
可以看到生產者往佇列testQueue中生產了7個數據。現在我們執行jms_produce,消費專案jms_consumer暫時不要啟動,因為我們要看看,生產者往activeMq中發數 據時,testQueue的狀態資料,然後啟動jms_consumer消費這消費後,activeMq中的testQueue的狀況。好了,現在我們執行jms_produce,然後瀏覽器中看到, 下面資訊(不記得怎麼用瀏覽器看activeMq中的資訊的,請回頭看看上面) 然後,我們再執行jms_consumer專案,把佇列testQueue中的資料給消費掉 控制檯 size有多少個生產者正在生產,應為上面jms_produce生產了7個數據後,它就直接關閉了,所以 這裡看到size=0,consumerCount表示正在有多少個消費者在連線這個佇列,看上面程式碼我們知道jms_consumer 一直在等待,一直在連線activeMq,所以consumerCount=1,enqueueCount表示佇列中有多少個數據, dequueueCount表示有多少個數據被消費過。 |
Queue的簡單例子2訊息的消費者接收訊息可以採用兩種方式:
1、consumer.receive() 或 consumer.receive(int timeout); 採用第一種方式,訊息的接收者會一直等待下去,直到有訊息到達,或者超時。後一種方式會註冊一個監聽器,當有訊息到達的時候, 會回撥它的onMessage()方法。下面舉例說明: 我們把上面的jms_consumer總的MessageRecive.java稍微修改下
能達到同樣的效果。 上面都是一個生產者,一個消費者,下面我們來看看一個生產者,多個消費者,消費結果是怎樣的。 對jms_consumer中的MessageRecive.java修改下
先啟動消費者jms_consumer,然後再啟動生產者,可以看到消費者的列印結果 發現,一個數據只能被消費一次,並且無法確定哪個資料被哪個消費者消費。 |
Topic的簡單例子與Queue不同的是,Topic實現的是釋出/訂閱模型,也就是一個數據可以被多個消費者消費。 將上面生產者和消費者中程式碼的
修改為
先啟動消費者,再執行生產者,看到列印結果如下 ,每個資料都被所有消費者消費 |
JMS的一些深入知識一個訊息物件分為三部分:訊息頭(Headers),屬性(Properties)和訊息體(Payload)。對於StreamMessage和MapMessage, 訊息本身就有特定的結構,而對於TextMessage,ObjectMessage和BytesMessage是無結構的。一個訊息可以包含一 些重要的資料或者僅僅是一個事件的通知。 訊息的Headers部分通常包含一些訊息的描述資訊,它們都是標準的描述資訊。包含下面一些值:
JMSDestination
JMSDeliveryMode
息仍然存在。後者在這種情況下表示訊息會被丟失。可以通過下面的方式設定:
JMSTimestamp
JMSExpiration
可以通過下面的方式設定:
提供者不確定消費者是否已經收到。 和JMS提供者定義的屬性。我們通常只適用自定義的屬性。 |
JMS+ActiveMq+Spring整合模擬處理新聞日誌場景新建專案jms_spring_produce模擬新聞專案,專案jms_spring_consumer模擬日誌處理專案, 為了便捷,專案都是用maven結構搭建的。 下面會貼部分原始碼,完整的專案請下載 生產者和消費者之間的資料互動,採用了自定義的類。由於生產者和消費者位於兩個獨立 的專案中,所以這些日誌物件(如截圖上的LoginLogDto.java/NewsVisitLogDto.java)都必 須序列號,並且生產者和消費之間這些物件都必須一模一樣。如果覺得麻煩,那可以通過 json來進行互動,或者將這些日誌物件抽出來作為一個獨立的jar專案,maven管理很方便的。 由於程式碼較多,又有配置之類的,這裡就不一一全部貼出來了,就貼部分. LoginLogDto.java
UserLoginLogProducer.java
LogSenderServiceImpl.java
生產者專案中的測試例子 TestUserLoginLogProducer.java
執行testSendMessage(),這樣就把資料傳送到ActiveMq了。 再來看看消費者的監聽類 UserLoginLogListener.java
把jms_spring_consumer部署到tomcat,啟動,就可以看到列印日誌了 注意事項,必須要有日誌配置,比如logback.xml,同時web.xml中必須配有listener
這裡再貼下jms_spring_produce中的jms_applicationContext.xml的配置
消費者jms_spring_consumer中的jms_applicationContext.xml
spring的配置,有很多引數,也有很多負責的功能,這裡就不一一介紹了。 上面總共給出了4個專案jms_produce、jms_consumer、jms_spring_produce、jms_spring_consumer,這裡打包上傳了,大家可以下載看看 |