消息隊列爲何說它像漏斗?

消息隊列爲何說它像漏斗?

寫在前面併發

對於 Web 服務而言,提高可擴展性的主要途徑是將耗時的同步工做改爲異步處理,從而容許將這些工做「外包」給多個 Worker 去作,或者提早完成可以預知的部分

(摘自Scalability_系統設計筆記 1)app

那麼,異步機制與可擴展性有什麼關係?異步

這要從(異步)並行處理的優點提及async

一.串行、併發與並行
可擴展性,意味着能經過向系統添加資源的方式應對不斷增長的工做量ide

對於多個任務,通常有 3 種執行策略:ui

  • 串行:一個接一個地同步執行,總耗時爲全部任務之和scala

  • 併發:多 CPU/多核併發執行,總耗時取決於最慢的任務耗時設計

  • 並行:異步並行執行,總耗時一樣取決於最慢的任務耗時

試想,若是工做量持續增加,串行模式的延遲將會愈來愈大,並且沒法經過加資源來解決,可擴展性無從談起code

併發模式雖然能夠經過加 CPU 來應對更多的工做量(即縱向擴展),但很快就會遭遇瓶頸,要麼達到頂配,要麼耗光預算,可擴展性也不是很好orm

並行模式下,因爲任務可以異步執行,咱們能夠加任意多的 Worker 來分擔工做量,可擴展性良好。而且,與併發模式相比,異步處理是非阻塞的(無需等待執行結果,單 CPU/單核就足夠了),意味着在(Worker)執行任務的同時,系統仍然可以輕鬆響應用戶請求

所以,相比之下異步(並行)可擴展性最高

二.異步的意義
除了可擴展性方面的優點外,異步更多的意義在於:

  • 可打斷/可暫停:容許分片執行,而沒必要一次作完

  • 可調度:容許更細粒度的時間管理,好比閒時主動執行、甚至離線執行

  • 並行的可能性:異步返回結果,意味着能夠交給別人、甚至交給一支軍隊來作

  • 解耦生產者和消費者:把 Worker 分離出去,使之可以獨立擴展,好比只加 Woker 不加 Web Server,相似於分離 Web 層和應用層

因此,React 從同步的 Stack reconciler 改成 Fiber reconciler,也具備這些意義:

既然任務可拆分(只要最終獲得完整 effect list 就行),那就容許並行執行(多個 Fiber reconciler + 多個 worker),首屏也更容易分塊加載/渲染(vDOM 森林)

(摘自徹底理解 React Fiber)

三.消息隊列
實現上,最多見的異步機制固然是消息隊列:

Message queues provide an asynchronous communications protocol, meaning that the sender and receiver of the message do not need to interact with the message queue at the same time.

由消息隊列提供異步通訊協議,消息的發送方和接收方不須要同時與消息隊列進行交互

例如,郵件系統中,發件人將郵件發出以後,能夠繼續處理其餘內容,而無需等待收件人響應:

消息隊列爲何說它像漏斗?

在用戶看來,任務是當即完成的,但其實是在一段時間以後才真正完成(所謂異步)

消息隊列的運做中有 3 個角色,消息的生產者、消費者以及經紀人(Broker):

  • 生產者:應用程序往隊列裏發佈任務後,當即告知用戶該任務的狀態

  • 消費者:Worker 拿到任務並執行,完成以後通知

  • Broker:從隊列裏取出任務並分發給 Worker,並負責管理任務的完整性,包括失敗重試、(根據 Worker 的實際狀態)動態調整分發策略等

P.S.另外,有個很是類似的概念叫任務隊列,區別在於消息隊列只負責接收、傳遞消息,任務隊列還跟蹤執行並返回結果,能夠看做特殊的消息隊列

Tasks queues receive tasks and their related data, runs them, then delivers their results.

固然,實際的消息隊列/任務隊列的實現更復雜一些,須要考慮各類問題:

  • 消息可能會丟失:好比消費者掛了,甚至消息隊列掛了

  • 消息可能會重發屢次:好比消費者作完忘記發送完成回執(ack)了

  • 可能出現忙閒不均的狀況:好比輪流分發的話,有些 Worker 接到的老是重活兒

  • 隊列可能會溢出:好比 Worker 太少或太忙,致使消息迅速堆積

P.S.關於消息隊列運做機制和使用場景的更多信息,見RabbitMQ Tutorials

四.漏斗模型
消息隊列就像一個漏斗(把橄欖油倒進瓶子裏),用來控制流量和流速:

消息隊列爲何說它像漏斗?

洶涌而至的消息從敞口流入,通過縮口以固定的流速輸出給(消息的)消費者

若是生產速率始終低於消費速率,倒進來當即就流走了,那麼就不須要漏斗(消息隊列)

若是生產速率始終大於消費速率,就會在漏斗中累積,最終填滿、溢出,致使消息丟失:

消息隊列爲何說它像漏斗?

P.S.這種現象稱爲Back pressure(反向壓力),下游消費速度限制了傳輸,此時能夠限制隊列大小,排滿了就返回 503,稍後重試(好比採起指數退避策略,讓重試間隔愈來愈長)

因此,只有生產速率在短時間內大於(而不是始終大於)消費速率的狀況下,漏斗纔有意義——用來吸取暫時的超量生產量:

The message queue provides temporary message storage when the destination program is busy or not connected.

五.利特爾法則
另外,排隊理論中一個有名的定理叫利特爾法則(Little’s law):

L = λW

L: average number of items in the queuing system
W: average waiting time in the system for an item
A: average number of items arriving per unit time

適用於任何穩定運轉的排隊系統:

A 「queuing system」 consists of discrete objects we shall call 「items」 that 「arrive」 at some rate to the 「system.」 Within the system the items may form one or more queues and eventually receive 「service」 and exit.

P.S.「穩定運轉」,是指不包括系統啓動、退出等過渡狀態

一些 item 以某種速度到達系統,開始排隊,最終排到服務並從隊列中退出:

到達 -> 排隊 -> 離開
L = λW就是說:

隊伍的平均長度 = 平均到達速度 \* (每一項的)平均等待時間

例如:

  • 酒窖:偶爾買一瓶放進去,平均每月買 8 瓶,朋友聚會時候喝掉一些,但多數時候窖裏都有 160 瓶,那麼,就能夠知道取出來喝的時候,每瓶酒在酒窖裏平均存放了 1.67 年(W = 160 / (8 * 12)),離陳釀還有一段距離

  • 郵箱:平均天天收到 50 封新郵件,郵箱裏多數時候有 150 封未讀郵件,那麼平均每 3 天(W = 150 / 50)處理一封郵件,能夠做爲郵件處理效率的衡量標準

  • 工廠:天天平均加工 1000 份原材料,在製品(WIP, work-in-process)數量平均有 45000 個,那麼每件產品的加工週期是 45 天(W = 45000 / 1000),週期比較長

  • 醫院:某地區平均天天誕生 5 名新生兒,待產媽媽平均會在產房待 2.5 天,那麼,產房一般住有 12.5 位(L = 5 * 2.5)待產媽媽,也就是說,產房牀位不能少於 13 張,對應的醫護人員也不能太少

三項中,只要知道兩個(易知的)就能粗略得出另外一個(難算的),這就是利特爾法則的意義

參考資料
Why is asynchronous architecture required for achieving scalability? Can you please provide a real life application/example?

Queueing Theory for Dummies:以及完整版Queueing Theory for Embedded Systems Designers

Little’s Law:利特爾法則最清楚的解釋

Module 4: Queuing Models and Little’s Law

What is message queuing?

Work Queues

Remote procedure call (RPC)

相關文章
相關標籤/搜索