京東到家開放平臺消息系統 - 進階之路

京東到家開放平臺,是一個面向商家以及第三方開發者 - 開放服務、持續賦能 O2O 業務的到家服務集成平臺。是商家數據與到家數據打通的橋樑,開放平臺、商家、到家三者之間的關係如圖所示。

    既然是數據通訊的橋樑,必然涉及到雙向通信,開放平臺提供大量的可調用的 API 接口,同時要求商家提供必要的接口供到家調用,比如新訂單的產生,訂單狀態變更,新增門店信息,促銷信息審覈等等。

    其中 API 接口由於是到家提供,相對來講比較穩定,而通知接口是商家提供,大量不確定因素都需要考慮,比如接口掛掉了,服務器宕機,網絡中斷等等,出了問題後還面臨如何快速發現,重新推送,推送頻次,重試時長,消息間會不會相互影響等問題。這些在消息系統設計之初都應該考慮到。

消息系統核心機制的設計

    開放平臺的消息系統(Business Message Queue,簡稱 BMQ)是基於內部系統的 MQ,這些 MQ 被內部各業務系統訂閱的同時,也被開放平臺訂閱,平臺進行格式轉化(標準消息或非標準消息)後,發送給商家,基本概念如圖所示。

    MQ 系統是京東自主研發的一款消息中間件系統,具有高可用、數據高可靠等特性。所以可以直接使用 MQ 來保證平臺自動重新推送消息,推送頻次,重試時長,以及消息的不丟失。那直接利用有什麼弊端呢?

    以新訂單消息爲例,當一個商家的接口掛了,就會不斷重試,甚至積壓,一旦積壓就會影響到沒有問題的商家。那怎麼解決這個問題?能不能針對商家維度進行消息推送?

    開放平臺的做法是,將重點 ka 與普通商家分離,所有 ka 商家獨立通道,ka 商家是可擴展的,當有必要時可以從非 ka 商家中提取單獨通道進行處理,這樣就將業務維度轉換成了商家維度,具體做法如圖所示。

    這樣簡單做可以了嗎?其實大家會發現一個問題,雖然 ka 商家間的影響小了,但是非 ka 商家仍然存在相互影響的問題,隨着業務增長,非 ka 商家間相互影響會越來越大,ka 商家通道的不同業務之間也會互相影響嗎?

    以沃爾瑪爲例,一個新訂單消息接口掛了,會不會影響售後消息呢?這是非常有可能的,同時也有一個非常簡單的做法就是按業務再次分離,因爲消息的種類非常多,每個商家的每個消息都單獨開闢消息通道,顯然要申請大量的 topic,不太利於維護和管理。

    開放平臺的做法是,每個通道增加專門的重試通道,一旦消息有問題,直接丟到重試通道即可,這樣就不影響正常的業務了,具體做法如圖所示。

    這樣就解決了大部分問題,在實際的運行過程中也發現是可行的。以爲可以高枕無憂了嗎?直到一次出現了常規通道中大量積壓,可是重試通道卻沒有數據,原來,我們 httpclient 允許的超時時間是 3 秒,超過 3 秒被認爲是失敗的,會丟到重試通道中,但實際上商家出現了大量慢響應,可能都在 2 秒多才返回,這樣引發不了發送失敗的條件,造成常規通道中的積壓。

    開放平臺針對這種情況的做法是,每個通道增加專門的降級通道,我們實時監控統計(kafka+flink)單商家單消息響應時間超過閾值的次數,對於規定時間內單商家單消息統計次數超過閾值的打上降級標。開放平臺在消費到家內部業務 MQ 時,有降級標的商家消息會直接進入對應的降級通道,不會進入常規通道。實時監控統計也會對恢復正常的單商家單消息清除降級標記,降級通道中執行失敗的消息處理方式同常規通道一樣,都會進入重試通道。具體策略如圖所示。

    以上基本上解決了大部分實際的場景,並且還具有可擴展空間,比如發現非 ka 的量較大時,可以將消息較多的商家提出單獨通道即可,總結就是採用三種通道結合具體策略達到了應對實際情況的方案,歸納如圖所示。

    到家開放平臺是如何保證消息順序問題?因爲平臺具備自動重試能力,所以沒有嚴格確保消息順序,只是使用了 MQ 自身保證的順序,平臺對調用商家接口定義爲僅消息通知,需要商家接到消息通知後反查到家接口,要求商家提供的消息接口具備排重能力。

消息系統的預警機制

    核心的設計雖然解決了實際環境中的各種問題,但這主要解決了平臺的風險,仍然面臨的問題有:

        1、接口出現了問題怎們能第一時間通知給商家,畢竟要求所有商家建立及時有效的報警也不太現實。

        2、非 ka 商家共用通道還是有一些相互影響的風險。

        3、知道了這些風險後,需要哪些工具來定位和處理問題呢。

    這時一套及時有效便捷的報警機制顯得尤爲重要。畢竟早知道,早通知,早處理是解決系統風險的第一要務,越早預警越可以規避不必要的風險。

    報警是建立在統計之上進行的,開放平臺的統計流程如圖。

    任何商家任何消息出現連續失敗達到一定閾值,就會發出報警,報警內容會以短信方式發送給商家負責人與開放平臺研發,如下所示。

    未有商家達到失敗閾值,但是多位商家失敗疊加導致 JMQ 報警,無法定位商家與接口時,我們有工具可以進行定位:按總失敗的量定位風險最大的商家。商家統計節點可以點進入看商家下每個消息接口總失敗次數。

    知道某個商家某個接口導致的失敗報警,經過與商家確認後,不能短時間修復,或者不再訂閱的,可以快速禁用此消息(消息將會被丟棄)。

    商家得知系統問題後,修復過程中沒必要持續報警,還可以手動停止報警(消息仍然保持重試,只停止報警,避免短信費用浪費)。

動態消息發佈的產生

    從上面核心功能的概念圖中可以看出,消息系統是需要訂閱大量底層 MQ 消息的,首先咱們先看一下以前京東到家開放平臺 BMQ 系統中是如何發佈一個消息接口的。

    同時也可以看下代碼維護的情況,BMQ 系統中有很多相似的 java 類,不利於代碼的觀賞與維護。

    總結弊端如下:

        1、接入新消息流程繁瑣複雜

        2、需要耗費最少 1 名研發的資源和時間

        3、每次新消息接入都是重複工作

        4、每次新消息接入都需系統上線

    爲了解決這些問題,開放平臺引入動態配置的思路,開放平臺的標準消息佔大部分,標準消息是和非標準消息相對的一個概念,標準消息就是無論原有消息的內容是什麼,最終轉化成標準格式,推送內容的字段統一,業務含義標準化。可配置的內容包括簡單的業務處理選擇,字段映射關係,默認值處理,還有簡單的邏輯。可配置的界面如圖所示。

    字段可配置細節如下圖。

    消息管理除了基本的增刪改功能,還需要通知服務端動態訂閱 mq(包括停止),這樣連 listener 都不用寫了,如果一旦發現有線上問題,還可以做到及時回退版本達到回滾的目的,管理界面如下。

    服務端實現動態訂閱 mq 的核心代碼如下。

// ips字段爲空爲廣播所有機器處理,不爲空爲指定某些機器執行
if (StringUtils.isEmpty(dynamicLoadingMessage.getIps()) || dynamicLoadingMessage.getIps().contains(IPUtil.getIp())) {
  // type=0需要加載的mq,非0需要卸載的mq
  if (dynamicLoadingMessage.getType() == 0) {
    openPlatformBMQEngine.getMessageConsumer().unsubscribe(dynamicLoadingMessage.getTopic());
    openPlatformBMQEngine.getMessageConsumer().subscribe(dynamicLoadingMessage.getTopic(), commonBMQListener);
    LOGGER.error("DynamicLoadingListener->onMessage->subscribe->dynamicLoadingMessage:{}", JsonUtils.toJson(dynamicLoadingMessage));
  } else {
    openPlatformBMQEngine.getMessageConsumer().unsubscribe(dynamicLoadingMessage.getTopic());
    LOGGER.error("DynamicLoadingListener->onMessage->unsubscribe->dynamicLoadingMessage:{}", JsonUtils.toJson(dynamicLoadingMessage));
  }
}

  通過以上處理後,發佈消息的流程如下。

    總結下動態 bmq 的特點:

        1、消息系統平臺化

        取消原有定製化接入流程,使用規則配置動態解析處理,實現平臺化統一入口接入新消息。

        2、接入低風險

        規避原有定製化手工編寫代碼上線接入方式,基於規則配置完成消息動態化,動態發佈消息從而有效避免開發上線過程中可能導致的風險,從而把風險降到最低。

        3、提高接入效率

        原有接入流程需要耗費約 2 個工作日的開發、測試和上線成本,新流程基於動態配置規避原有的開發、測試、上線流程,接入新消息時間縮短至 1 分鐘,後期甚至可達到使非開發人員有能力自行接入。

總結

  本篇着重介紹了 BMQ 系統是如何保證穩定性,易用性及簡潔性,從實踐的角度結合理論解決了諸多問題,不僅滿足了當前系統的實際需要,也可以應對未來一段時間的業務增長需求。從理論的角度上看,平臺還有很多不足,在未來的日子裏我們也會持續結合實踐進行優化。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-_ojzdrhx9GIaN0xJzeFrA