微服務架構已成爲了互聯網的熱門話題之一,而這也是互聯網技術發展的必然階段。然而,微服務概念的提出者 Martin Fowler 卻強調:分佈式調用的第一原則就是不要分佈式。數據庫
縱觀微服務實施過程當中的弊端,能夠推斷出做者的意圖,就是但願系統架構者可以謹慎地對待分佈式調用,這是分佈式系統自身存在的缺陷所致。但不管是 RPC 框架,仍是 REST 框架,都由於駐留在不一樣進程空間的分佈式組件,而引入了額外的複雜度。於是可能對系統的效率、可靠性、可預測性等諸多方面帶來負面影響。服務器
信用算力自2016年開始實施微服務改造,經過消息隊列(Message Queue),後文簡稱MQ,來規避微服務存在的缺陷,實現金融級數據服務。如下是一些使用場景和心得。架構
1、案例介紹併發
先來看一個當前的真實業務場景。框架
對於經過信息流獲客的企業而言,當用戶註冊時,因業務需求會調用用戶服務,而後執行一系列操做,註冊 -> 初始化帳戶信息 -> 邀友獎勵發放 -> 發放優惠券 -> ... -> 信息流數據上報。異步
用戶服務的開發人員壓力很是大,由於須要調用很是多的服務,業務耦合嚴重。若是當時帳戶服務正在執行發版操做,那麼初始化帳戶動做會失敗。然而平臺通過不斷的迭代更新,後續又新增了一個簽到業務,新註冊用戶默認簽到一次。這就須要修改用戶服務,增長調用簽到服務的接口。每當遇到此種狀況,開發用戶服務的同窗就很是不爽了,爲何老是我?新增簽到業務和用戶服務又有什麼關係?分佈式
爲解決此類重度依賴的問題,咱們在架構層面引入了 MQ,用來規避微服務之間重度耦合調用的弊端。新架構以下圖:微服務
用戶完成註冊動做後,只須要往 MQ 發送一個用戶註冊的通知消息,下游業務如須要依賴註冊相關的數據,訂閱註冊消息的 topic 便可,從而實現了業務的解耦。性能
看完上述真實的案例後,你們可能產生疑惑,到底什麼是 MQ,使用 MQ 又有什麼好處?適合使用 MQ 的場景和不適合使用 MQ 的場景有哪些不一樣?大數據
2、什麼是 MQ?
簡單來講,MQ(MessageQueue)是一種跨進程的通訊機制,用於上下游傳遞消息。
適合使用 MQ 的場景有:
一、上游不關心下游執行結果,例如上述案例中用戶註冊後,咱們並不關心帳戶是否初始化,是否上報了信息流等;
二、異步返回執行時間長:例如上述案例中,當邀友獎勵發放,須要經歷不少風控規則,執行時間比較長,可是用戶並不關注獎勵什麼時候發放。
不適合使用MQ場景
調用方實時關注執行結果,例如用戶發起註冊動做後,須要馬上知道,註冊結果是成功仍是失敗,這種須要實時知道最終執行結果的場景,就不適合使用MQ。
3、使用MQ的好處:
一、解耦
二、可靠投遞
三、廣播
四、最終一致性
五、流量削峯
六、消息投遞保證
七、異步通訊(支持同步)
八、提升系統吞吐、健壯性
目前業內比較主流的 MQ 包括 RocketMQ、ActiveMQ、RabbitMQ、Kafka等,關於性能、存儲、社區活躍度等各方面的技術對比已經不少,本文再也不重複。
但咱們發現經過簡單的選型對比,很難抉擇到底選擇哪款MQ產品。由於金融行業對於數據一致性以及服務可用性的要求很是高,因此任何關於技術的選項都顯得尤其重要。
經調研,如微衆銀行、民生銀行、平安銀行等國內知名的互聯網銀行和直銷銀行表明,都在使用 RocketMQ,且 RocketMQ 出生在阿里系,經受過各類生產壓力的考驗,很是穩定。而且,目前此項技術已經捐增給 Apache 社區,社區活躍度很是高。另外 RocketMQ 開發語言是Java,開發同窗遇到解決不了的問題點,或者不清楚的概念,能夠直接 Debug 源碼。通過多方面的比較,咱們選擇 RocketMQ 做爲規避微服務弊端的利器。
MQ 是一種跨進程的通訊機制,用於上下游傳遞消息,目前信用算力將 RocketMQ 應用於解耦、流量削峯、分佈式事務的處理等幾個場景。
1、解耦
一般解耦的作法是生產者發送消息到 MQ,下游訂閱 MQ 的特定 topic,當下遊接收到消息後開始處理業務邏輯。
那麼,消息發送方到底應該是由誰來承擔?是服務提供者在處理完RPC請求後,根據業務需求開始發送消息嗎?但此刻開發人員就會抱怨爲何老是我?爲何處理完業務後須要發送 MQ?
爲此,在解耦的過程當中經過訂閱數據庫的 BinLog 日誌,開發了一套 BinLog 日誌解析模塊,專門解析日誌,而後生成 JSON 字符串後發送消息到 MQ,下游訂閱 MQ 便可。流程以下:
目前全部須要依賴下游服務的業務線,其數據變更都採用此方案。
方案優缺點:
優勢:
一、服務之間依賴徹底解耦,任何基於註冊行爲的業務變動,都無需依賴上游,只需訂閱MQ便可;
二、系統的穩定性和吞吐量增長了,用戶註冊的響應時間縮短了;
缺點:
一、引入MQ後系統複雜性增長,維護成本增長;
二、從註冊開始到所有數據初始化結束的總體時間增長了;
2、流量削峯
每逢遇到會員日的時候,平臺會發送大量的會員福利活動通知,以短信、站內信、PUSH 消息的方式通知註冊用戶。全部的消息會在很短的時間所有推送到消息中心,同時正常的業務通知任然有大量業務消息推送到消息中心。爲保障平臺的穩定性和可靠性,在消息中心前置了多種 topic,如短信、推送、站內提醒。消息中心接收到消息後會所有寫入不一樣 topic 的 MQ,多個消費者來消費並把信息推送給終端用戶。
3、分佈式事務
用戶在平臺上支付他訂購某種業務的時候,須要涉及到支付服務、帳戶服務、優惠券服務、積分服務,在單體模式下這種業務很是容易實現,經過事務便可完成,僞代碼以下:
然而,在微服務的狀況下,本來經過簡單事務處理的卻變得很是複雜,若引入兩階段提交(2PC)或者補償事務(TCC)方案,則系統的複雜程度會增長。
信用算力的作法是經過本地事務 + MQ 消息的方式來解決, 雖然 RocketMQ 也支持事務消息,可是其餘主流 MQ 並無此項功能,因此綜合考慮採用以下方案:
方案優缺點:
優勢:
一、用最小的代價實現分佈式事物,以達到數據最終一致性;
二、方案很是靈活,任何環節均可以人爲控制;
缺點:
一、複雜性增長了,業務操做的時候須要寫入 tc_message 表以及發送 MQ,同時還須要考慮狀態超時未變動的補發機制以及告警處理機制;
二、用戶看到的數據,存在有短暫不一致的狀況;
使用 RocketMQ 3年多了,整體來講運行的很是穩定,基本上沒有發生過生產事故,下面說說這幾年使用下來的心得體會:
一、一個應用盡量用一個 Topic,消息子類型用 tags 來標識。Topic 名稱和 Tags 名稱能夠自行設置。Producer,Consumer都須要規範,要作到見名知意。發送消息時候必須攜帶 Tags,消費方在訂閱消息時,才能夠利用 Tags 在 Broker 作消息過濾。
二、每條消息在業務層面有惟一標識碼,方便在系統出現異常的狀況,能夠經過業務維度查詢。舉個栗子,當用戶在平臺註冊成功後,會以 Topic 和 UserID 做爲惟一標識碼(topic_user_10011),服務器會爲每一個消息建立索引,該消息會持久化入庫,以防未來定位消息丟失等問題。下游收到消息後會以 Topic+Key 方式來記錄消費行爲,包括消息日期、當前機器IP地址、處理結果等;也能夠經過 Topic+Key 的方式來查詢這條消息內容,包括消息被誰消費,以及這條 MQ 在每一個環節的處理狀態。
三、消息發送成功或者失敗,都須要記錄 log 日誌,且必須打印 sendresult、MsgID、惟一標識碼。
四、因爲上游會作消息重試機制,因此下游消息必需要作冪等處理。
五、須要封裝 MQ 的 API 在封裝後,API 需屏蔽底層 MQ 的特性,開發人員無需關注究竟是用的哪一個 MQ 來支持本地分佈式事物、MQ 消息自動入庫、自動打印日誌,減小開發人員操做成本。
總的來講,MQ 是一個互聯網架構中常見的解耦利器,在這3年中,信用算力在微服務中一直使用 MQ 來爲金融客戶提供高質量的數據服務。雖然 MQ 不是惟一方案,可是從目前階段來看,的確是一種很是不錯的解決方案。
本文做者:
潘志偉:信用算力技術總監,QCon 演講嘉賓,十多年 Java 從業經驗,精通微服務架構,精通大數據。擁有億級用戶平臺架構經驗,萬級併發的API網關經驗。
本文做者:中間件小哥
本文爲雲棲社區原創內容,未經容許不得轉載。