讀構建可擴展分散式系統:方法與實踐06非同步消息傳遞

来源:https://www.cnblogs.com/lying7/p/18415886
-Advertisement-
Play Games

1. 非同步消息傳遞 1.1. 通信是分散式系統的基礎,也是架構師需要納入其系統設計的主要問題 1.2. 客戶端發送請求並等待伺服器響應 1.2.1. 這就是大多數分散式通信的設計方式,因為客戶端需要得到即時響應後才能繼續 1.2.2. 並非所有系統都有這個要求 1.3. 使用非同步通信的方式,客戶端( ...


1. 非同步消息傳遞

1.1. 通信是分散式系統的基礎,也是架構師需要納入其系統設計的主要問題

1.2. 客戶端發送請求並等待伺服器響應

  • 1.2.1. 這就是大多數分散式通信的設計方式,因為客戶端需要得到即時響應後才能繼續

  • 1.2.2. 並非所有系統都有這個要求

1.3. 使用非同步通信的方式,客戶端(稱為生產者)將其請求發送到中間消息傳遞服務

1.4. 生產者對他們發送的請求“發後即忘”(fire and forget)

  • 1.4.1. 一旦請求被傳遞到消息傳遞服務,生產者就會進入其邏輯中的下一步,並確信它發送的請求最終得到處理

  • 1.4.2. 消息機制提高了系統的響應能力,因為生產者不必等到請求處理完成

1.5. 非同步消息傳遞是可擴展系統架構的一個組成部分

1.6. 消息傳遞機制在經歷請求高峰和低谷的系統中特別有吸引力

  • 1.6.1. 在高峰時段,生產者可以將請求添加到隊列中並快速響應客戶端,而無須等待請求被處理

1.7. 消息隊列可以分佈在多個代理之間以擴展消息吞吐量,也可以複製隊列來提高可用性

1.8. 消息機制並非不存在風險

  • 1.8.1. 將消息副本放在隊列中,如果隊列保留在記憶體中,則消息可能會丟失

1.9. 將消息副本放在隊列中,如果隊列保留在記憶體中,則消息可能會丟失

2. 消息傳遞簡介

2.1. 非同步消息傳遞平臺是一個成熟的技術領域

  • 2.1.1. 久負盛名的IBM MQ系列出現於1993年,至今仍是企業系統的中流砥柱

  • 2.1.2. Java消息傳遞服務(JMS)是一種API級別的規範,由多個JEE供應商實現和支持

  • 2.1.3. RabbitMQ,可以說是部署最廣泛的開源消息傳遞系統

2.2. 消息傳遞原語

  • 2.2.1. 消息隊列

  • 2.2.1.1. 存儲一系列消息的隊列

  • 2.2.2. 生產者

  • 2.2.2.1. 將消息發送到隊列

  • 2.2.2.2. 生產者將消息發送到代理上的命名隊列

  • 2.2.3. 消費者

  • 2.2.3.1. 從隊列中取出消息

  • 2.2.3.2. 多個消費者可以從同一個隊列中獲取消息

  • 2.2.3.3. 消費者獲取消息有兩種行為模式,即拉取或推送

>  2.2.3.3.1. 在拉取(也稱為輪詢)模式中,消費者向代理髮送請求,代理用下一條可供處理的消息進行響應

>  2.2.3.3.2. 在推送模式下,消費者告知代理自己希望從隊列中接收消息

  >   2.2.3.3.2.1. 消費者提供了一個回調函數,當消息可用時應調用該函數

  >   2.2.3.3.2.2. 然後消費者就會阻塞(或執行其他工作)​,消息代理會在有消息可用時將消息傳遞給回調函數進行處理

  >   2.2.3.3.2.3. 使用推送模式更加高效

2.2.3.3.2.3.1. 避免了代理可能被來自多個消費者的請求壓垮,並使代理能更高效地實現消息傳遞

2.2.3.3.2.3.2. 消費者確認後,代理就可以將消息標記為已傳遞,並將其從隊列中刪除

2.2.3.3.2.3.3. 如果使用自動確認,消息傳遞給消費者之後,在消息處理之前代理就會收到確認

  • 2.2.4. 消息代理

  • 2.2.4.1. 消息代理是一個服務,管理著一個或多個隊列

  • 2.2.4.2. 消息代理可以在同一硬體上管理多個隊列

2.3. 通常會有消費者希望確保消息在確認之前得到完全處理

  • 2.3.1. 它將使用手動確認的方式

  • 2.3.2. 可以防止出現消息已經被傳遞給消費者,但由於消費者崩潰而導致消息未被處理的問題

  • 2.3.3. 確實會增加消息確認的延遲

2.4. 無論選擇何種確認模式,未確認的消息都有效地保留在隊列中,並將在稍後的某個時間傳遞給另一個消費者處理

2.5. 消息持久化

  • 2.5.1. 預設情況下,消息隊列通常保存在記憶體中,以便為生產者和消費者提供儘可能快的服務

  • 2.5.2. 只要記憶體充足,在記憶體中管理隊列的開銷就是最小的

  • 2.5.2.1. 如果伺服器崩潰,那麼它確實有丟失消息的風險

  • 2.5.3. 為了防止消息丟失,隊列可以設置成可持久化的

  • 2.5.3.1. 當生產者將消息放入隊列時,只有消息寫入磁碟後操作才會完成

  • 2.5.3.2. 如果消息代理髮生故障,在重新啟動時它可以將隊列內容恢復到失敗前的狀態,並且不會丟失任何消息

  • 2.5.4. 持久隊列會固有地增加發送操作的響應時間,但數據安全性卻得到了提高

  • 2.5.5. 代理通常會在記憶體和磁碟上維護隊列內容,這樣就能在正常操作時以最小的開銷將消息發送給消費者

2.6. 發佈-訂閱

  • 2.6.1. 在發佈-訂閱系統中,消息隊列被稱為主題

  • 2.6.2. 一個主題一般都是一個消息隊列,它會將每個發佈的消息傳遞給多個訂閱者之一

  • 2.6.3. 發佈者與訂閱者分離,訂閱者的數量可以動態變化

  • 2.6.3.1. 須對現有系統進行任何更改即可添加新的訂閱者,架構具有高度的可擴展性

  • 2.6.4. 發佈-訂閱模式給消息代理帶來了額外的性能負擔

  • 2.6.4.1. 利用推送的消息消費模型為發佈-訂閱架構提供了最有效的解決方案

  • 2.6.5. 發佈-訂閱消息傳遞機制是構建分散式事件驅動架構的關鍵組件

  • 2.6.5.1. 在事件驅動的架構中,多個服務可以使用消息代理主題發佈與某些狀態變更相關的事件

  • 2.6.5.2. 服務可以通過訂閱主題來註冊感興趣的各種事件類型

  • 2.6.5.3. 該主題發佈的每個事件都會發送給所有感興趣的消費者服務

2.7. 消息複製

  • 2.7.1. 在非同步系統中,消息代理可能會是一個潛在的故障點

  • 2.7.2. 系統或網路故障可能導致代理不可用,從而使系統無法正常運行

  • 2.7.3. 大多數消息代理都允許在多個代理之間以物理方式複製邏輯隊列和主題,每個代理都在自己的節點上運行

  • 2.7.4. 消息隊列複製的最常見方法是領導者-追隨者(leader-follower)架構

  • 2.7.4.1. 一個代理被指定為領導者,生產者和消費者分別通過該領導者發送和接收消息

  • 2.7.4.2. 追隨者被稱為熱備用,是領導者的副本,如果領導者發生故障,則追隨者頂上

  • 2.7.5. 在故障場景下,生產者和消費者可以通過切換訪問追隨者來繼續操作,稱之為故障轉移

  • 2.7.5.1. 故障轉移在消息代理的客戶端庫中實現,因此對生產者和消費者來說是透明的

  • 2.7.6. 實現一個可以執行隊列複製的代理是一件複雜的事情

  • 2.7.6.1. 不要考慮使用自己的複製方案或任何其他複雜的分散式演算法

  • 2.7.6.2. 你的解決方案將不如現有解決方案有效,開發成本將超出你的預期

3. RabbitMQ

3.1. 是分散式系統中使用最廣泛的消息代理之一

3.2. RabbitMQ代理採用Erlang語言構建,主要為AMQP(Advanced Message Queuing Protocol,高級消息隊列協議)開放標準提供支持

  • 3.2.1. AMQP誕生於金融行業,致力於定義合作協議

  • 3.2.1.1. 它是一種二進位協議,為執行該協議的不同產品提供互操作性

  • 3.2.2. RabbitMQ支持開箱即用,支持AMQP v0-9-1,並通過插件支持v1.0

3.3. 消息、交換機和隊列

  • 3.3.1. 代理基於一個被稱為交換機(exchange)的概念實現了一個消息傳遞模型,它為創建消息傳遞拓撲提供了一種靈活的機制

  • 3.3.2. 交換是對接收生產者消息並傳遞給代理隊列的過程的一種抽象

  • 3.3.3. 直連交換機通常用於根據匹配路由鍵將每條消息傳遞到一個目標隊列

3.4. 分發和併發

  • 3.4.1. 通道不是線程安全的,這意味著每個線程都需要對通道進行獨占訪問

  • 3.4.2. 線程的生命周期和調用由伺服器平臺控制,而不是由你的代碼控制

  • 3.4.3. 輪詢效率很低,因為它涉及繁忙的等待,即使沒有消息可用,也要求消費者不斷詢問消息

  • 3.4.3.1. 高性能系統中不會使用這種方法

  • 3.4.4. 推送模型

3.5. 與大多數消息代理一樣,RabbitMQ在消費速率跟生產速率相當時表現最佳

  • 3.5.1. 當隊列增長到大約有數萬條消息時,管理隊列的線程將承受更多的開銷

  • 3.5.2. 預設情況下,代理使用運行節點40%的可用記憶體

3.6. 數據安全與性能權衡

  • 3.6.1. 所有消息傳遞系統都面臨著性能與可靠性權衡的兩難境地

  • 3.6.2. 核心問題是消息傳遞的可靠性,通常稱為數據安全

3.7. 可用性與性能權衡

  • 3.7.1. 單個代理髮生故障屬於單點故障,因此如果代理崩潰或經歷短暫的網路故障,就會導致系統不可用

  • 3.7.2. 高可用性的典型解決方案是代理和隊列複製

  • 3.7.3. RabbitMQ提供了兩種支持高可用性的方法,分別是鏡像隊列和仲裁隊列

  • 3.7.3.1. 需要部署兩個或多個RabbitMQ代理並配置成一個集群

  • 3.7.3.2. 每個隊列都有一個領導者版本,以及一個或多個追隨者

  • 3.7.3.3. 發佈者向領導者發送消息,領導者負責將每條消息複製給追隨者

  • 3.7.3.4. 消費者也連接到領導者,當領導者收到消息成功處理的應答時,消息也會從追隨者中刪除

  • 3.7.3.5. 由於所有發佈者和消費者的隊列行為都由領導者執行,仲裁隊列和鏡像隊列雖然都提升了可用性,但不支持負載均衡

>  3.7.3.5.1. 消息吞吐量受到領導者副本的性能限制
  • 3.7.3.6. 關鍵的區別在於如何複製消息,以及在領導者發生故障的情況下如何選擇新的領導者
>  3.7.3.6.1. 仲裁本質上意味著超過半數

>  3.7.3.6.2. 如果有五個隊列副本,那麼至少需要三個副本(領導者和兩個追隨者)來持久保存新發佈的消息

>  3.7.3.6.3. 仲裁隊列實現了RAFT演算法以便管理副本,併在領導者不可用時選擇新的領導者

>  3.7.3.6.4. 仲裁隊列必須是持久性的,因此主要適用於數據安全性和可用性優先於性能的用例

  >   3.7.3.6.4.1. 在故障處理方面,它比鏡像隊列的實現更有優勢

4. 消息傳遞模式

4.1. 競爭消費者

  • 4.1.1. 消息傳遞系統的一個常見需求是儘可能快地消費隊列中的消息

4.2. 可用性

  • 4.2.1. 如果一個消費者發生故障,系統仍然可用,這個消費者的消息份額只是簡單地分發給其他競爭消費者

4.3. 故障處理

  • 4.3.1. 如果一個消費者發生故障,它未確認的消息將傳遞給另一個隊列消費者

4.4. 動態負載均衡

  • 4.4.1. 新的消費者可以在高負載期間啟動併在負載減少時停止,而無須更改任何隊列或消費者配置

4.5. 嚴格遵守一次處理原則

  • 4.5.1. 在非同步消息傳遞系統中,重覆處理消息來源於兩個問題

  • 4.5.1.1. 第一個是來自發佈者的重覆發佈

>  4.5.1.1.1. 一些消息代理提供了對這種重覆檢測的支持,從而確保重覆的消息不會被髮布到隊列中

>  4.5.1.1.2. 利用每條消息在客戶端生成的唯一冪等鍵值

  >   4.5.1.1.2.1. 發佈者只需要將特定的消息屬性設置為唯一值

>  4.5.1.1.3. 代理利用緩存來存儲冪等鍵值並檢測重覆項,有效地消除了隊列中的重覆消息,解決了第一個問題

>  4.5.1.1.4. 在消費者端,代理將消息傳遞給消費者後,消費者對消息進行了處理,但之後無法發送應答(消費者崩潰或網路丟失應答)​,就會發生重覆給消費者傳遞消息的情況
  • 4.5.1.2. 第二個是消費者多次消費
>  4.5.1.2.1. 消費者有義務防止重覆處理

>  4.5.1.2.2. 為已處理的消息維護一個緩存或冪等鍵值資料庫

>  4.5.1.2.3. 大多數代理將設置一個消息頭,指示消息是否為重新傳遞

  >   4.5.1.2.3.1. 消費者可以用它來實現冪等性

  >   4.5.1.2.3.2. 它不能保證消費者已經處理了該消息

  >   4.5.1.2.3.3. 它只是告訴你代理已傳遞過該消息並且消息仍未得到應答
  • 4.5.1.3. 兩者都需要解決,以確保每條消息都只處理一次

4.6. 有害消息

  • 4.6.1. 最常見的可能是生產者發送了錯誤的消息,消費者無法處理

  • 4.6.2. 導致消費者崩潰

  • 4.6.2.1. 在研發和測試系統中最為常見

  • 4.6.2.2. 有時這些問題也會流入生產環境,而消費者發生故障肯定會導致一些嚴重的運營難題

  • 4.6.3. 導致消費者拒絕消息,因為它無法成功處理消息負載

  • 4.6.4. 有害消息將被傳遞給另一個消費者,會得到可預測的、不良結果

  • 4.6.4.1. 如果沒辦法檢測到有害消息,則會無限期地傳遞它們

  • 4.6.4.2. 最好的結果是只占用處理能力,減少系統吞吐量

  • 4.6.5. 有害消息處理的方案是限制重新傳遞消息的次數

  • 4.6.5.1. 當達到重新傳遞的限制時,消息會自動轉移到一個收集問題請求的隊列

>  4.6.5.1.1. 這個隊列在傳統上被稱為死信隊列
  • 4.6.6. 每個消息傳遞平臺實現有害消息處理的確切機制都有所不同

  • 4.6.7. 有害消息處理的最後一部分是診斷出消息被重定向到死信隊列的原因

  • 4.6.8. 最重要的是你需要設置某種形式的監視警報給工程師發送消息處理失敗的通知


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. Redis 1.1. 2009年首次發佈 1.1.1. 更註重原始性能和簡單性,而不是數據安全性和一致性 1.2. 主要吸引力在於它能夠同時充當分散式緩存和數據存儲 1.3. 維護一個記憶體中的數據存儲,也稱為數據結構存儲(data structure store) 1.4. 配置Redis將每 ...
  • 大家好,我是湯師爺~ 今天聊聊SaaS業務架構的業務能力分析。 業務能力概述 簡單來說,業務能力是企業“做某事的能力”。 業務能力描述了企業當前和未來應對挑戰的能力,即企業能做什麼或需要做什麼。業務能力建模的關鍵在於定義了企業做什麼,而不是如何做(由業務流程描述)。 以人才招聘為例,大多數公司都需要 ...
  • 1. 強一致性 1.1. 最終一致資料庫通過跨多台機器分區和複製數據集來獲得可擴展性,其代價是要跨副本維持強數據一致性以及允許衝突寫入 1.1.1. 在更新數據對象後,不同的客戶端可能會看到該對象的舊值或新值,直到所有副本都收斂到最新值 1.2. 另一類分散式資料庫提供一種可替代的模型,即強一致性數 ...
  • 1. 最終一致性 1.1. 在一些應用領域,通常談論的是銀行和金融行業,最終一致性根本不合適 1.2. 事實上,最終一致性在銀行業已經使用了很多年 1.2.1. 支票需要幾天時間才能在你的賬戶上進行核對,而且你可以輕鬆地開出比賬戶餘額多的支票 1.2.2. 當處理檢查並建立一致性後,你才能看到一些後 ...
  • 大家好,我是湯師爺~ 今天聊聊SaaS架構中的流程架構分析。 業務流程的概念 業務流程是企業為實現目標而制定的一套系統化的工作方法。它由一系列有序的業務活動組成,按照既定規則將資源(輸入)轉化為有價值的結果(輸出)。這一過程需結合企業的具體情況和可用資源,旨在為客戶創造價值,同時達成企業目標。 通過 ...
  • 1. 可擴展資料庫基礎 1.1. 絕大多數應用程式都是基於關係資料庫技術構建的 1.2. 資料庫必須存儲大量數據,為分佈在全球的客戶端提供快速的查詢響應,並且全天候可用 1.3. NoSQL資料庫採用簡單的數據模型,可以複製和分區以支持海量數據集和請求量 1.4. Facebook以使用MySQL管 ...
  • 1. 微服務 1.1. 微服務的起源可以追溯到2008年左右 1.1.1. 在Amazon,​“兩個比薩原則”成為一個單系統組件團隊規模的管理原則,後來被稱為微服務 1.1.1.1. 每個內部團隊都應該小到可以用兩個比薩餅喂飽 1.1.2. Amazon和Netflix是微服務架構的先驅,他們在20 ...
  • 1. 無伺服器的魅力 1.1. 對於某些應用程式,負載在工作時間可能很高,而在非工作時間可能很低或者不存在 1.2. 其他應用程式後臺流量可能在99%的時間里都很低 1.2.1. 一旦到了一些大型節目的門票發佈時間,負載需求可能會在數小時內飆升至平均水平的10000倍,然後回落至正常水平 1.3.  ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...