消息中間件與Spring集成和場景實例

消息中間件與Spring集成和場景實例

消息中間件與Spring集成和場景實例

spring的xml配置

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

class="org.apache.activemq.spring.ActiveMQConnectionFactory">

啟動activemq


消息中間件與Spring集成和場景實例


消息中間件與Spring集成和場景實例


消息隊列中間件(簡稱消息中間件)是指利用高效可靠的消息傳遞機制進行與平臺無關的數據交流,並基於數據通信來進行分佈式系統的集成。通過提供消息傳遞和消息排隊模型,它可以在分佈式環境下提供應用解耦、彈性伸縮、冗餘存儲、流量削峰、異步通信、數據同步等等功能,其作為分佈式系統架構中的一個重要組件,有著舉足輕重的地位。

消息中間件一般兩個功能,解耦和異步處理,分別舉個例子吧

解耦合:

比如我們做一個微博產品中的好友系統,就很需要使用消息中間件

當我們添加一個關注的時候, 涉及以下幾個子系統

推薦系統,需要根據你關注的人給你做數據分析

搜索系統,需要根據你的數據建立索引

feed系統,需要根據你關注的人,發送一條新鮮事

統計系統 用於數據統計,瞭解產品情況

而如果直接在加關注的流程裡進行這些操作,可能帶來風險,所以,會引入mq來解耦合,因此就像你說的,一般是 "單向傳輸" 的(當然這不是絕對的,取決於你係統複雜度),而且發往mq的數據一般都不大,比如 from_uid, to_uid 就行了,一般都不會很大,如果發送的數據不滿足你的要求,這個時候,需要調用好友系統提供的接口了

異步處理:

有的時候,我們一個操作可能會耗時比較久,所以,並不會在主要業務流程裡進行處理

比如,我們在刪除一個用戶的時候,可能會有很多關聯數據的操作,為了儘快的響應以及解耦合,我們會將這個消息發送給其他系統,讓它們根據需求自己處理

目前開源的消息中間件可謂是琳琅滿目,能讓大家耳熟能詳的就有很多,比如 ActiveMQ、RabbitMQ、Kafka、RocketMQ、ZeroMQ 等。不管選擇其中的哪一款,都會有用的不趁手的地方,畢竟不是為你量身定製的。有些大廠在長期的使用過程中積累了一定的經驗,其消息隊列的使用場景也相對穩定固化,或者目前市面上的消息中間件無法滿足自身需求,並且也具備足夠的精力和人力而選擇自研來為自己量身打造一款消息中間件。但是絕大多數公司還是不會選擇重複造輪子,那麼選擇一款合適自己的消息中間件顯得尤為重要。就算是前者,那麼在自研出穩定且可靠的相關產品之前還是會經歷這樣一個選型過程。

在整體架構中引入消息中間件,勢必要考慮很多因素,比如成本及收益問題,怎麼樣才能達到最優的性價比?雖然消息中間件種類繁多,但是各自都有各自的側重點,選擇合適自己、揚長避短無疑是最好的方式。如果你對此感到無所適從,本文或許可以參考一二。

4、各類消息隊列簡述

ActiveMQ 是 Apache 出品的、採用 Java 語言編寫的完全基於 JMS1.1 規範的面向消息的中間件,為應用程序提供高效的、可擴展的、穩定的和安全的企業級消息通信。不過由於歷史原因包袱太重,目前市場份額沒有後面三種消息中間件多,其最新架構被命名為 Apollo,號稱下一代 ActiveMQ,有興趣的同學可行了解。

RabbitMQ 是採用 Erlang 語言實現的 AMQP 協議的消息中間件,最初起源於金融系統,用於在分佈式系統中存儲轉發消息。RabbitMQ 發展到今天,被越來越多的人認可,這和它在可靠性、可用性、擴展性、功能豐富等方面的卓越表現是分不開的。

Kafka 起初是由 LinkedIn 公司採用 Scala 語言開發的一個分佈式、多分區、多副本且基於 zookeeper 協調的分佈式消息系統,現已捐獻給 Apache 基金會。它是一種高吞吐量的分佈式發佈訂閱消息系統,以可水平擴展和高吞吐率而被廣泛使用。目前越來越多的開源分佈式處理系統如 Cloudera、Apache Storm、Spark、Flink 等都支持與 Kafka 集成。

RocketMQ 是阿里開源的消息中間件,目前已經捐獻個 Apache 基金會,它是由 Java 語言開發的,具備高吞吐量、高可用性、適合大規模分佈式系統應用等特點,經歷過雙 11 的洗禮,實力不容小覷。

ZeroMQ 號稱史上最快的消息隊列,基於 C 語言開發。ZeroMQ 是一個消息處理隊列庫,可在多線程、多內核和主機之間彈性伸縮,雖然大多數時候我們習慣將其歸入消息隊列家族之中,但是其和前面的幾款有著本質的區別,ZeroMQ 本身就不是一個消息隊列服務器,更像是一組底層網絡通訊庫,對原有的 Socket API 上加上一層封裝而已。

目前市面上的消息中間件還有很多,比如騰訊系的 PhxQueue、CMQ、CKafka,又比如基於 Go 語言的 NSQ,有時人們也把類似 Redis 的產品也看做消息中間件的一種,當然它們都很優秀,但是本文篇幅限制無法窮極所有,下面會針對性的挑選 RabbitMQ 和 Kafka 兩款典型的消息中間件來做分析,力求站在一個公平公正的立場來闡述消息中間件選型中的各個要點。

5、選型要點概述

衡量一款消息中間件是否符合需求需要從多個維度進行考察,首要的就是功能維度,這個直接決定了你能否最大程度上的實現開箱即用,進而縮短項目週期、降低成本等。如果一款消息中間件的功能達不到想要的功能,那麼就需要進行二次開發,這樣會增加項目的技術難度、複雜度以及增大項目週期等。

6、具體技術選型指標1:功能維度

功能維度又可以劃分個多個子維度,大致可以分為以下這些。

優先級隊列:

優先級隊列不同於先進先出隊列,優先級高的消息具備優先被消費的特權,這樣可以為下游提供不同消息級別的保證。不過這個優先級也是需要有一個前提的:如果消費者的消費速度大於生產者的速度,並且消息中間件服務器(一般簡單的稱之為 Broker)中沒有消息堆積,那麼對於發送的消息設置優先級也就沒有什麼實質性的意義了,因為生產者剛發送完一條消息就被消費者消費了,那麼就相當於 Broker 中至多隻有一條消息,對於單條消息來說優先級是沒有什麼意義的。

延遲隊列:

當你在網上購物的時候是否會遇到這樣的提示:“三十分鐘之內未付款,訂單自動取消”?這個是延遲隊列的一種典型應用場景。延遲隊列存儲的是對應的延遲消息,所謂“延遲消息”是指當消息被髮送以後,並不想讓消費者立刻拿到消息,而是等待特定時間後,消費者才能拿到這個消息進行消費。延遲隊列一般分為兩種:基於消息的延遲和基於隊列的延遲。基於消息的延遲是指為每條消息設置不同的延遲時間,那麼每當隊列中有新消息進入的時候就會重新根據延遲時間排序,當然這也會對性能造成極大的影響。實際應用中大多采用基於隊列的延遲,設置不同延遲級別的隊列,比如 5s、10s、30s、1min、5mins、10mins 等,每個隊列中消息的延遲時間都是相同的,這樣免去了延遲排序所要承受的性能之苦,通過一定的掃描策略(比如定時)即可投遞超時的消息。

死信隊列:

由於某些原因消息無法被正確的投遞,為了確保消息不會被無故的丟棄,一般將其置於一個特殊角色的隊列,這個隊列一般稱之為死信隊列。與此對應的還有一個“回退隊列”的概念,試想如果消費者在消費時發生了異常,那麼就不會對這一次消費進行確認(Ack), 進而發生回滾消息的操作之後消息始終會放在隊列的頂部,然後不斷被處理和回滾,導致隊列陷入死循環。為了解決這個問題,可以為每個隊列設置一個回退隊列,它和死信隊列都是為異常的處理提供的一種機制保障。實際情況下,回退隊列的角色可以由死信隊列和重試隊列來扮演。

重試隊列:

重試隊列其實可以看成是一種回退隊列,具體指消費端消費消息失敗時,為防止消息無故丟失而重新將消息回滾到 Broker 中。與回退隊列不同的是重試隊列一般分成多個重試等級,每個重試等級一般也會設置重新投遞延時,重試次數越多投遞延時就越大。舉個例子:消息第一次消費失敗入重試隊列 Q1,Q1 的重新投遞延遲為 5s,在 5s 過後重新投遞該消息;如果消息再次消費失敗則入重試隊列 Q2,Q2 的重新投遞延遲為 10s,在 10s 過後再次投遞該消息。以此類推,重試越多次重新投遞的時間就越久,為此需要設置一個上限,超過投遞次數就入死信隊列。重試隊列與延遲隊列有相同的地方,都是需要設置延遲級別,它們彼此的區別是:延遲隊列動作由內部觸發,重試隊列動作由外部消費端觸發;延遲隊列作用一次,而重試隊列的作用範圍會向後傳遞。

事務性消息:

事務本身是一個並不陌生的詞彙,事務是由事務開始(Begin Transaction)和事務結束(End Transaction)之間執行的全體操作組成。支持事務的消息中間件並不在少數,Kafka 和 RabbitMQ 都支持,不過此兩者的事務是指生產者發生消息的事務,要麼發送成功,要麼發送失敗。消息中間件可以作為用來實現分佈式事務的一種手段,但其本身並不提供全局分佈式事務的功能。

關注我:私信回覆"555"獲取Java高級架構資料


分享到:


相關文章: