久久国产乱子伦精品免费M,亚洲一区二区三区91,欧美国产在线视频,国产精品视频久久

吐血整理:一份不可多得的架構師圖譜!

概述
架構師圖譜”是一個很宏大的命題,特別是優秀的架構師自身也是“由點到面再到圖”,一點點成長積累起來。
嘗試寫這篇文章的目的更多的是結合自身的一些架構、研發、管理經驗對現階段做一個復盤總結,所以這里更偏向于后端圖譜,依賴于開源技術、云原生或者其他第三方服務。
這里會重點介紹一些技術棧、設計理念以及適應場景,這些可以作為我們選型時的依據。所謂“架構即決策”,是在一個有約束的盒子中尋求最優解。
這個有約束的盒子是團隊經驗、成本、資源、進度、業務所處階段等編織、摻雜在一起的綜合體。
本質上無優劣,但是存在恰當的架構用在合適的軟件系統中,而這些就是決策的結果。

一個技術圖譜:

吐血整理:一份不可多得的架構師圖譜!
本文重點聚焦在微服務和常用的消息隊列,包括相關的選型以及一些理論基礎。

完整的思維導圖:

吐血整理:一份不可多得的架構師圖譜!
微服務
微服務是一種軟件架構風格,它是以專注于單一責任與功能的小型功能區塊為基礎,利用模塊化的方式組合出復雜的大型應用程序,各功能區塊使用與語言無關的 API 集相互通信。
微服務架構有別于更為傳統的單體服務,可將應用拆分成多個核心功能。每個功能都被稱為一項服務,可以單獨構建和部署。
這也體現了可擴展的基本思想:將原本大一統的系統拆成多個小部分,擴展時只修改其中一部分,通過這種方式減少改動范圍,降低改動風險。
微服務架構涵蓋了服務的多個方面,包括網關、通信協議、服務注冊/發現、可觀察性、如何合理的劃分等等。

| 理論基礎

微服務的理論基礎主要用來指導微服務架構設計、服務拆分,確定合適的服務粒度和邊界。
在做微服務之前我們首先要想明白我們現有系統面臨什么樣的問題,為什么需要微服務,隨后才是怎么做。
微服務很多核心理念其實在半個世紀前的一篇文章中就被闡述過了,而且這篇文章中的很多論點在軟件開發飛速發展的這半個世紀中竟然一再被驗證,這就是康威定律(Conway’s Law)。

在康威的這篇文章中,最有名的一句話就是:

Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations.

中文直譯大概的意思就是:設計系統的組織,其產生的設計等同于組織之內、組織之間的溝通結構。
最初這篇文章只是描述作者自己的發現和總結,后來“人月神話”中,引用這個觀點,并將其“吹捧”成現在熟知的“高位定律”。
其中的一些核心觀點可以概括如下:
  • 組織溝通方式決定系統設計,對于復雜的系統,聊設計就離不開聊人與人的溝通,解決好人與人的溝通問題,才能有一個好的系統設計
  • 時間再多一件事情也不可能做的完美,但總有時間做完一件事情,這與架構設計的“簡單、合適、演化”思維不謀而合
  • 線型系統和線型組織架構間有潛在的異質同態特征,更直白的說,你想要什么樣的系統,就搭建什么樣的團隊,定義好系統的邊界和接口,團隊內應該是自治的,這樣將溝通成本維持在系統內部,每個子系統就會更加內聚
  • 大的系統組織總是比小系統更傾向于分解,面對復雜的系統及組織,往往可以采用分而治之
但是當我們的業務和組織架構復雜度比較高的時候,很多概念只從技術角度很難去抽象,這就需要我們自上而下,建立起通用語言,讓業務人員和研發人員說一樣的話,把思考層次從代碼細節拉到業務層面。越高層的抽象越穩定,越細節的東西越容易變化。
通過對不同領域的建模,逐步確定領域范圍和業務邊界,這也就是領域驅動設計(DDD)。
DDD 是一種在面向高度復雜的軟件系統時,關于如何去建模的方法論,它的關鍵點是根據系統的復雜程度建立合適的模型,DDD 中的界限上下文也完美匹配了微服務的高內聚、低耦合特性,這也為我們微服務的劃分提供了強有力的基礎。
DDD 實施的一般步驟是:
  • 根據需求劃分出初步的領域和限界上下文,以及上下文之間的關系
  • 進一步分析每個上下文內部,識別出哪些是實體,哪些是值對象
  • 對實體、值對象進行關聯和聚合,劃分出聚合的范疇和聚合根
  • 為聚合根設計倉儲,并思考實體或值對象的創建方式
  • 在工程中實踐領域模型,并在實踐中檢驗模型的合理性,倒推模型中不足的地方并重構
但是 DDD 也不是銀彈,特別是在一些新業務場景,本身就充滿了很多的不確定性,一次性把邊界劃清楚并不是一件很容易的事。
大家在一個進程里,調整起來會相對容易,然后讓不同的界限上下文各自演化,等到了一定程度之后再考慮微服務也是一個不錯的選擇。

| 網關

作為微服務的統一入口,也肩負著整個微服務的流量接入、管理、聚合、安全等,從服務分層的角度可以劃分為接入網關和業務網關。
接入網關接入網關提供最基礎的流量接入和安全防護能力,側重于全局,與業務無關。
域名&DNS:作為服務的流量入口,對外通過域名和 DNS 提供服務,國內域名廠商一般都依托于共有云或被共有云廠商收購,用來完善自由的云生態。
像阿里的萬網,騰訊的 DNSPod 等,也有國外的 AWS,GoDaddy 和 Namecheap 等,可以用作 .me 等國內無法托管或備案域名的管理。
其次也可以借助DNS(HTTPDNS、EDNS)實現跨地域、運營商網絡等負載均衡,實現異地多活、就近訪問、容災等。
負載均衡(LB):主要負責請求的轉發代理,按機器負載來分配流量等,對外提供 VIP,這里的負載可以寬泛的理解為系統的壓力,可以用 CPU 負載來衡量,也可以用連接數、I/O 使用率、網卡吞吐量等來衡量。
負載均衡器按服務層級來劃分,除了前邊提到的 DNS,還有集群級別的硬件負載均衡,以及機器級別的軟件負載均衡。
DNS/硬件負載均衡(F5/A10)主要用來應對海量用戶的訪問,中小量用戶使用無疑會增加更多的維護和采購成本。
軟件負載均衡可以選擇自研或上云,LVS、Keepalived 主要用于四層(IP+端口)的負載均衡,在四層的基礎之上如果要實現應用層(域名/URL/用戶會話)等的 7 層負載均衡,可以使用 Nginx、Keepalived 的組合。
除此之外,網關也負責服務整體的安全防護,SSL,IPV6 等:
  • 安全防護目的是保護服務數據以及可用性,例如防范常見的 DDOS/CC 網絡攻擊,反爬蟲,自定義訪問控制,自研成本往往比較高,可以借助云上一系列的高防、防火墻服務。
  • SSL(TLS)用來提供外部 https 訪問,https 可以防止數據在傳輸過程中不被竊取、改變,確保數據的完整性,在支付或者用戶登錄等敏感數據場景,可以起到一定的保護作用,同時 https 頁面對搜索引擎也比較友好。
  • IPV6,全球 43 億 IPV4 地址已經在 2019 年年底耗盡,網信辦在 2018 年開始就已經推行各大運營商、CDN 廠商、互聯網核心產品支持 IPV6,我們公司之前也是試點之一。IPV6 的支持只需要增加一條“AAAA”DNS記錄,將域名解析到自持 IPV6 的 IP/VIP 即可。IPV4 到 IPV6 由于存在兼容性等問題,一定是長期共存的,過渡方案可以采用 IPV6 代理(IPV6 代理轉發到 IPV4 服務)或者雙棧(同時支持 IPV6 和 IPV4)。

業務網關:

吐血整理:一份不可多得的架構師圖譜!
業務網關作為業務的最上層出口,一般承擔起業務接入或者 BFF 的工作,例如基礎的路由、鑒權、限流、熔斷降級、服務聚合、插件化能力,并可以通過可視化界面管理網關配置。
可選框架有基于 OpenResty 的 Kong、APISIX 以及其他語言相關的 SpringCloud Gateway、gRPC-Gateway 等等。
國內開源的 Goku、Kratos、go-zero go 框架,有很多比較有意思的組件實現,我們日常業務上也可以借鑒。
鑒權:鑒權的目的是為了驗證用戶、請求等的有效性,例如用戶身份鑒權(JWT/Oauth2/Cookie),請求鑒權(請求簽名、請求加密),鑒權邏輯也花樣繁多,大多需要基于業務定制化,通過網關插件能很好的集成進來。
限流:限流是為了做一定的流量控制,防止對系統產生過大壓力從而影響整個服務。可以基于單臺機器或整個集群限流,常見的方式有限制總量和限制速率,超過的則排隊或丟棄,例如令牌桶(彈性)/漏桶(勻速)算法。
熔斷降級:熔斷作為服務斷路器,當下游的服務因為某種原因突然變得不可用或響應過慢(這里既可以指單次請求也可以指一段時間),上游服務為了保證自己整體服務的可用性,不再繼續調用目標服務,直接返回,這樣也能對整體鏈路起到保護作用。
如果目標服務情況好轉則恢復調用,同時結合降級策略提升服務的魯棒性。常見的有Hystrix/Resilience4J(Hystrix 雖然已停止更新,但現有功能已經能滿足大多業務場景)。
重試:大量網絡 IO,避免不了會出現因網絡抖動,出現連接失敗或者超時,重試可以提高請求的最終成功率,削平服務毛刺。
但重試也有可能放大故障,所以可以結合退避策略(backoff)、限制單點重試、限制鏈路重試這些策略進行優雅的重試,同時也可以采用更加激進的“對沖請求”提前(tp99 時間未響應時)發起重試請求,降低系統時延。
插件化:各個網關集成插件的方式盡不相同,但是目的都是為了集成技術人員編寫的一些業務相關的通用能力,例如前邊提到的身份鑒權、請求鑒權等等。
另外作為業務網關插件,也可以編寫一些基礎業務(API 鑒權、請求格式化)邏輯,直接透傳請求到服務層,省去很多 BFF 和上下游對接的工作。
BFF:Backend For Frontend,可以按照業務邏輯,以串行、并行和分支等結構編排多個服務 API,為服務提供聚合、適配、裁剪(只返回需要的字段)功能,核心是 API 的動態編排以滿足日益增長的業務邏輯,降低前端與微服務之間的對接成本。
BFF 并不意味著只能由后端實現,也可以在前端通過 GraphQL 等 API 查詢語言實現。

| 協議

服務間的通信方式是在采用微服務架構時需要做出一個最基本的決策,統一的協議標準也能大大降低服務的聯調和維護成本。
HTTP REST:REST 更確切的講是指的 API 設計風格,而不是協議標準。通常基于使用 HTTP,URL,和 JSON 這些現有的廣泛流行的協議和標準。符合 REST 設計風格的 API 稱作 RESTful API。
在實際應用中大多實現的是偽 REST API,例如用 POST 請求同時實現資源的增刪改,或者為了請求的擴展性,資源的增刪改查都使用 POST JSON。
RPC:RPC 協議描繪了客戶端與服務端之間的點對點調用流程,包括 stub、通信、RPC 消息協議部分。可以基于 TCP,也可以基于 http。
在實際應用中,還需要考慮服務的高可用、負載均衡等問題,所以產品級的 RPC 框架除了點對點的 RPC 協議的具體實現外,還應包括服務的發現與注冊、提供服務的多臺 Server 的負載均衡、服務的高可用等更多的功能。
目前的 RPC 框架大致有兩種不同的側重方向,一種偏重于服務治理(Dubbo、Motan),另一種偏重于跨語言調用(Thrift/GRPC)。
RPC vs HTTP REST 優點:
  • 更清晰的 API 定義,例如 gRPC 協議的定義文件 proto,自身就可以作為很好的 API 文檔,日常開發中也可以把 proto 文件獨立版本庫管理,精簡目錄結構,方便不同的服務引用。
  • 更好的傳輸效率,通過序列化和反序列化進一步壓縮網絡傳輸數據,不過序列化、反序列化也會有一定的性能損耗,protobuf 可以說很好的兼顧了這兩點。
  • 更合適的容錯機制,可以基于實際的業務場景,實現更合適的超時控制與異常重試機制,以應對網絡抖動等對服務造成的影響。
在一些特定場景,例如:OpenAPI、BFF 等,HTTP REST 可以更大程度上降低外部團隊的接入成本。并且 RPC 也有調試不便、多語言互通需要對應的 SDK 支持這些問題,各有利弊。
綜合考慮來看,除了一些特定場景,如果我們已經有相對完善的基礎設施支撐(RPC 框架、服務治理),RPC 可以為一個更合適的選擇。

| 服務注冊/發現

服務注冊主要是通過將微服務的后端機器 IP、端口、地域等信息注冊起來,并結合一定的發現機制使客戶端的請求能夠直連具體的后端機器。

從實現方式上可以分為服務端模式與客戶端模式:

吐血整理:一份不可多得的架構師圖譜!

服務端模式:也可以說是傳統模式,通過借助負載均衡器和 DNS 實現,負載均衡器負責健康檢查、負載均衡策略,DNS 負責實現訪問域名到負載均衡器 IP/VIP 的映射。通過直接暴露域名和端口的方式提供客戶端訪問。

吐血整理:一份不可多得的架構師圖譜!

客戶端模式:可以借助注冊中心實現,注冊中心負責服務的注冊與健康檢查,客戶端通過監聽配置變更的方式及時把配置中心維護的配置同步到本地,通過客戶端負載均衡策略直接向后端機器發起請求。

從兩種模式的實現方式上可以看出:
①服務端模式注冊與發現都由服務端完成,這樣可以使客戶端專注在自身的業務實現,但是由于依賴負載均衡器,也就是集中式的 proxy,proxy 需要維護雙向連接,也很容易使自己成為系統瓶頸,可用性的高低直接決定了服務質量。
并且 DNS 緩存機制也會導致故障發生時,遷移并不能及時完成。當然在服務量少,且負載均衡器有 VIP 的情況下,我們也可以不使用 DNS。
②客戶端模式注冊與發現由配置中心和客戶端共同完成,通過分布式的方式,可以避免出現 proxy 節點性能瓶頸問題,但是可靠性與性能瓶頸很容器出現在配置中心上,并且客戶端的也需要一定的接入成本。
好在開源的已經有很成熟的架構方案與豐富的客戶端 SDK,例如 etcd/ZooKeeper/Consul。

Consul 提供開箱即用的功能,etcd 社區和接入易用性方面更優一些,他們之間的一些具體區別:

吐血整理:一份不可多得的架構師圖譜!

|?配置中心

配置中心從使用場景來講,一類是前邊講到的服務注冊、發現和 KV 存儲,例如 etcd/ZooKeeper/Consul,在 Kubernetes 場景下也可以通過 ConfigMap/Secret 將配置寫入本地文件、環境變量或者共享的 Volume 中。
這樣沒有了中心服務的依賴和客戶端的接入,可以實現一些老舊服務的無侵入式改造。
但是作為配置中心,除了基礎的配置數據,一些情況下還要開放給非開發人員(測試、運維、產品)使用,完善的控制臺、權限管理、Dashbord 的支持,也非常重要,這類可以參考 Nacos(阿里開源)/Apollo(攜程開源)。
Nacos 在讀寫性能上優于 Apollo,但是功能特性(例如權限管理)稍遜于 Apollo。

| 可觀察性

在控制論中,可觀察性是用系統輸出到外部的信息來推斷系統內部運運行狀態的一種度量方式。
在云原生時代,容器和服務的生命周期是緊密聯系在一起的,相較在傳統的單體服務運行在物理主機或者虛擬機當中,排查問題的時候顯得非常不便,這種復雜性導致了一個定義研發運營效率的 MTTR(平均故障修復時間)指標急劇增加。
所以這里更強調的是微服務的可觀察性,需要提前想好我們要如何觀察容器內的服務以及服務之間的拓撲信息、各式指標的搜集等,這些監測能力相當重要。
可觀察性三大支柱圍繞 Tracing(鏈路追蹤)、Logging(日志)和 Metrics(度量)展開,這三個維度幾乎涵蓋了應用程序的各種表征行為,開發人員通過收集并查看這三個維度的數據時刻掌握應用程序的運行情況。

很長一段時間,這三者是獨立存在的,隨著時間的推移,這三者已經相互關聯,相輔相成。

吐血整理:一份不可多得的架構師圖譜!
①鏈路追蹤
鏈路追蹤為分布式應用的開發者提供了完整的調用鏈路還原、調用請求量統計、鏈路拓撲、應用依賴分析等工具,可以幫助開發者快速分析和診斷分布式應用架構下的性能瓶頸,提高微服務時代下的開發診斷效率以及系統的可觀察性。

為了解決不同的分布式系統 API 不兼容的問題,誕生了 OpenTracing 規范,OpenTracing 中的 Trace 可以被認為是由多個 Spacn 組成的 DAG 圖。

吐血整理:一份不可多得的架構師圖譜!
OpenTracing 專注在 tracing,除此之外還有包含了 Metrics 的 OpenCensus 標準,以及由 CNCF 推出,融合 OpenTracing 和 OpenCensus 的 OpenTelemetry。
OpenTelemetry 旨在實現云原生時代可觀察性指標(Tracing、Logging、Metrics)的統一收集和處理,同時提供推動這些標準實施的組件和工具。

OpenTracing 中的佼佼者當屬 Jaeger、Zipkin、Skywalking。他們之間的一些對比:

吐血整理:一份不可多得的架構師圖譜!
Zipkin 開源時間長,社區相對豐富,Jaeger 更加輕量,也是 Istio 推薦方案,SkyWalking 支持部分語言(Java、PHP、Python 等)的無侵入式接入。另外 APM(應用性能)監控的支持也會影響到我們的選型。
除此之外,面對線上海量請求,如果采用抽樣采樣策略,那就需要支持一定的流量染色,把我們核心關注的請求(例如鏈路中發生了錯誤、部分請求耗時過高等)都進行采樣。
可以通過結合 opentelemetry-collector 以及開箱即用的 tailsamplingprocessor 構建 Pipeline 插件實現。
②日志
服務間的鏈路日志能否幫助我們判斷錯誤發生的具體位置,這類業務日志主要集中在訪問日志/打點日志等等。
隨著大數據的興起,我們對數據的分析解讀能力越來越強,日志作為原始數據則體現出了更大的價值,例如用戶的行為分析,反垃圾,輿情分析等等。
業務日志:這類日志重點在于通過不同級別的日志,及時發現分析系統存在的異常。
RFC 5424 定義的 8 中日志級別:
  • Emergency:system is unusable
  • Alert:action must be taken immediately
  • Critical:critical conditions
  • Error:error conditions
  • Warning:warning conditions
  • Notice:normal but significant condition
  • Informational:informational messages
  • Debug:debug-level messages
在實際使用過程中可能會對日志級別進行簡化和調整,一般來講 Warning 及以上的日志是需要重點關注的,需要做好及時的監控告警,Warning 以下的日志也可以輔助問題的定位。
日志寫入可以選擇寫入消息隊列,也可以選擇落地磁盤,將關心的結構化或非結構化日志、業務模塊信息(如果是細粒度的微服務,可以選擇將日志放同一模塊收集),以及級別、時間(who、when、where、how、what)等要素正確的寫入正確寫入后再收集到日志服務。
寫入消息隊列需要考慮消息隊列的選型以及做好可用性和積壓監控,寫入磁盤需要考慮寫入性能以及日志的切割清理,例如 Golang 的 zap+rotatelogs 組合。
日志收集的話,由于 Logstash 資源消耗相對比較大,虛擬機環境中可以使用 Filebeat 來替代,更嚴苛的線上或容器環境,可以使用 Fluentd/Fluentd Bit。日志最終匯總到 ES 和 Kibana 做展示,通過 Esalert 定制告警策略。
大數據日志:大數據日志本質上也對應著我們一定的業務場景,但大多是海量日志、高吞吐量場景,所以對海量日志的收集和存儲是較大的挑戰。
實現方案我們可以采用高吞吐量的流式中間件,例如 Kafka/Plusar 等,在結合流式處理(Flink)或者批處理(Spark)系統,將數據匯總到 Hadoop 進行分析,這里涉及到的中間件和數據庫可參考后續章節。
③指標
指標是有關系統的離散的數據點,這些指標通常表示為計數或度量,并且通常在一段時間內進行匯總或計算。
一般用來做基礎的資源監控和業務監控:
  • 資源監控:CPU、內存、IO、fd、GC等
  • 業務監控:QPS、模調、耗時分布等
Zabbix 作為老牌的監控系統,適合更復雜的物理機、虛擬機、數據庫等更復雜的場景,同時也擁有更豐富的圖形化界面。
但是 Prometheus 作為云原生的代表作,與 Kubernetes、容器等能更好的結合,協同 Grafana 實現可定制化的界面,另外存儲基于 TSDB,相比于關系型數據庫也有更好的擴展性。
以 Prometheus 為例,支持的數據類型有:
  • Counter 只增不減的計數器,例如請求數(http_requests_total)。基于此數據模型,使用 Prometheus 提供的強大 PromQL 表達式能夠拓展出更加適合開發觀察的指標數據。分鐘增量請求:increase(http_requests_total[1m]) 分鐘 QPS:rate(http_requests_total[1m])
  • Gauge 可增可減的時刻量,例如 Go 語言協程數(go_goroutines) 波動量:delta(go_goroutines[10m])
  • Histogram 直方圖,不同區間內樣本的個數。例如,耗時 50ms-100ms 每分鐘請求量,100ms-150ms 每分鐘請求量。
  • Summary 概要,反應百分位值。例如,某 RPC 接口,95% 的請求耗時低于 150ms,99% 的請求耗時低于 200ms。

Prometheus 指標支持 pull 和 push 模式:

  • Pull:服務暴露 metrics 接口,指標內存更新,Prometheus server 定時拉取,性能更好,但要考慮易失性
  • Push:指標推送 push-gateway,Promethus server 從 gateway 拉取,適用瞬時業務場景(定時任務)

| Service Mesh

我們前邊講的服務發現、熔斷降級、安全、流量控制、可觀察性等能力。這些通用能力在 Service Mesh 出現之前,由 Lib/Framework 通過一些切面的方式完成,這樣就可以在開發層面上很容易地集成到我們的應用服務中。

但是并沒有辦法實現跨語言編程,有什么改動后,也需要重新編譯重新發布服務。理論上應該有一個專門的層來干這事,于是出現了 Sidecar。

第一代 Service Mesh,像 Linkerd,后邊又出現了第二代 Service Mesh,Istio,職責分明,分離出處數據面和控制面。

但是 Sidecar 作為代理層,避免不了性能損耗(CPU 序列化反序列化 UDS),所以 proxyless service mesh 重新被提起,和之前的 「RPC + 服務發現治理」區別是啥?

感覺這個名詞營銷味道略重。其實不能簡單的 “Proxyless Service Mesh” 理解為 “一個簡單的 RPC 框架,暴露了幾個超時參數到配置中心來控制”,它重在統一協議、API。

這樣就便于基于統一的協議實現 proxyless mesh 和 proxy mesh 的互通,可以同時滿足性能敏感型和快速迭代型的業務場景。
吐血整理:一份不可多得的架構師圖譜!
他們相輔相成,豐富了 service mesh 的形態:
吐血整理:一份不可多得的架構師圖譜!
servicemesh 對于微服務基礎設施的一種演進,但不代表他已經非常成熟了,相反像遷移成本高,甚至一些可用性設計還不如業務自己做那么靈活。

這些現實的問題還擺在面前,我覺得這也是屬于技術進化的一種趨勢,當一項技術足夠成熟的時候,又回衍生出新的復雜度問題,從而又需要發展出新技術解決。

消息隊列
在計算機科學中,消息隊列是一種進程間通信或同一進程的不同線程間的通信方式,軟件的貯列用來處理一系列的輸入,通常是來自用戶。
消息隊列提供了異步的通信協議,每一個貯列中的紀錄包含詳細說明的數據,包含發生的時間,輸入設備的種類,以及特定的輸入參數。

也就是說:消息的發送者和接收者不需要同時與消息隊列交互。消息會保存在隊列中,直到接收者取回它。

吐血整理:一份不可多得的架構師圖譜!
實際應用場景中,消息隊列也經常作為中間件,用于異步解耦、削峰填谷、數據廣播、錯峰與流控、最終一致性等,在一些核心的大數據分析、交易支付等場景也經常扮演重要角色。
關于服務解耦,會有很多人質疑,消息隊列是否能真正解耦,我的理解是:數據要發生流轉,系統之間要有依賴關系。
例如上游服務直接讀寫下游存儲、中間件進行數據交互,解耦則更側重于將易于變化的復雜度轉移,對下游存儲、中間件的依賴,通過消息隊列轉化為雙方的弱接口(消息payload)依賴。
但如果上游是本身是依賴的下游 API,這種方式就需要考慮有多個下游時,自身復雜度和可用性的變化。
消息隊列的選型主要側重以下幾點:
  • HA:自身的高可用性保障,避免消息隊列的引入而影響整體服務的可用性
  • 高吞吐:在面對海量數據寫入能否保持一個相對穩定、高效的數據處理能力
  • 功能豐富性:是否支持延遲消息、事務消息、死信隊列、優先級隊列等
  • 消息廣播:是否支持將消息廣播給消費者組或者一組消費者
  • 消息堆積能力:在數據量過大時,是否允許一定消息堆積到broker
  • 數據持久性:數據持久化策略的采用,也決定著數據在宕機恢復后是否會丟失數據
  • 重復消費:是否支持ack機制,在消費者未正確處理消息時,支持重新消費
  • 消息順序性:針對順序消費的場景保證數據按寫入時間的順序性
這里著重對比一下 Redis、RabbitMQ/RocketMQ、Kafka、Plusar。

| Redis

Redis 實現消息隊列可以通過 List 類型、Pub/Sub、Stream(Redis 5.0)類型來實現,HA 使用多副本或者集群的方式。
作為消息隊列使用起來非常方便,但是也有很多的弊端:
  • 功能豐富性:只支持普通的消息類型
  • 數據持久性:Pub/Sub 只提供緩沖區廣播能力,不進行持久化,List/Stream 即使基于 aof 和 rdb 持久化策略,但是并沒有事務性保障,在宕機恢復后還是存在丟失數據的可能性
  • 消息堆積能力:List 隨長度增大,內存不斷增長;Pub/Sub 只在緩沖區內堆積,緩沖區滿消費者強制下線;Stream 創建時可以指定隊列最大長度,寫滿后剔除舊消息
除此之外,List 類型無法支持消息廣播,和 Pub/Sub 一樣也不支持重復消費。
結合整體來看 Redis 作為消息隊列大多數只應用在數據量小,對丟失數據不敏感的業務場景,適用范圍較小,復雜業務并且有一定運維支撐的情況下,可以直接考慮企業級消息中間件。

| RabbitMQ vs Kafka vs RocketMQ

這幾個可以作為企業級消息中間件的代表,而 RocketMQ 在設計之初就借鑒了很多 RabbitMQ、Kafka 的設計理念,例如:Routing、多副本、順序寫(IO),也廣泛應用在淘寶雙十一等場景。
HA:在 HA 方面他們都是通過副本的方式,區別是 RabbitMQ 是集群級別的副本,Kafka 是多 partiton 和 ISR、選舉機制,而 RocketMQ 通過多(master/slave)副本同時保障 NameServer 和 Broker。
高吞吐:Kafka 和 RocketMQ 通過直接操作文件系統,相比于 RabbitMQ,順序寫能大幅度提升數據的處理速度。
Kafka 為了進一步提升消息的吞吐量,可以采用客戶端緩沖隊列的方式批量發送,但也會存在宕機丟失數據的可能性,可以通過設置 batch.size 與 linger.ms 來動態調整,相比于 RocketMQ 更加靈活。
Kafka 的 partition 機制的確會帶來性能的提升,但是在 Topic 不斷增多的情況下,眾多的 partition 及副本也將順序寫逐步退化為隨機寫,并且擴容時,由于 hash 值的變化,也會涉及到大量 partiton 數據的遷移。
RocketMQ 采用 commitlog 的方式實現全局寫,所以能支持更多的 Topic,擴容也不涉及大量數據的遷移。
功能豐富性:Kafka 只有基礎的消息類型,RabbitMQ 支持優先級隊列,通過 TTL 和死信隊列可以實現消息的延遲和重試,但是需要提前創建好對應重試頻率的隊列。
例如:1s 重試隊列,10s 重試隊列,RocketMQ 則內置了 18 個重試頻率“1s 5s 10s 30s 1m 2m……”,另外也具有獨有的 2PL 事務消息,很好的保障業務邏輯與消息發送的一致性。
重復消費:他們三者都采用 ACK 機制保障了單條消息重復消費的能力,Kafka 通過 offset 和 partition 特殊的 ttl 機制(segment 過期,按文件名順序清理),能支持通過重置 offset 來回溯歷史數據。
消息順序性:RabbitMQ 和 RocketMQ 可以保證寫入同一 topic 的順序性,但是在多個消費者同時消費的情況下還是會出現亂序的情況。
在數據量較大的時候,我們也可以通過單個消費者消費,再按照一定的分發策略分配給多個消費者執行,只不過會提升整體復雜度,同時會帶來更多的 HA、維護成本考量。
Kafka 可以保障單個 partition 的順序性,并且每個 partiton 只允許一個消費者來消費(N:1),這就從策略上避免了多消費者的情況,在數據量較大的情況下,可以通過劃分更多的 partition 提升數據處理能力。
綜合來講,RabbitMQ、RocketMQ 使用 Queue 模型,豐富的消息隊列功能,更多的應用在業務場景,Kafka 基于 Streaming 模型,結合批處理、流式處理,更多的應用在大數據分析場景。

| Pulsar

Pulsar 作為 Apache 開源、云原生的消息中間件,誕生之初就引發了很大的關注。

設計上避免了 Kafka 遇到的功能豐富性、擴容等方面的問題,采用計算、存儲分離的架構,broker 層只作為“API 接口層”,存儲交給更專業的 bookeeper,由于 broker 層的無狀態性,結合 Kubernetes 等非常方便的進行擴容。

吐血整理:一份不可多得的架構師圖譜!
并且 Pulsar 支持多個消費模型提升消費者處理能力,例如:exclusive、failover、shared、key-shared 等。
可以說綜合了 Kafka 和其他消息中間件的眾多優點:
  • HA、高吞吐:和 Kafka 類似,通過多 partition 和選舉機制功,除此之外,還支持豐富的跨地域復制能力
  • 功能豐富性:可以支持秒級的延遲消息,以及獨特的重試隊列和私信隊列
  • 消息順序性:為了實現 partition 消息的順序性,和 Kafka 一樣,都需要將消息寫入到同一 broker,區別是 Kafka 會同時存儲消息在該 broker,broker 和 partiton 綁定在一起,而 Pulsar 可以將消息分塊(segment)后,更加均勻的分散到 bookeeper 節點上,broker 只需要記錄映射關系即可,這樣在資源擴容時,可以更加快速便捷
像能量守恒定律一樣,系統的復雜度往往也是守恒的,實現即高性能又高可用的消息中間件需要的技術復雜性,不會憑空消失,只會從一個地方轉移到另一個地方。
消息隊列本質上可以理解為 feature+fs,只不過存儲、計算分離架構,將各層間的職責分離,使每一層都能專注在自身領域,以應對海量數據和更加復雜多變的環境,這也是現在新技術發展的一個趨勢。
作為后起之秀,的確可以站在巨人的肩膀上,避免很多設計上的不足,同時引入一些新的架構理念,但是要成功的在其中分一杯羹,同樣也要面臨用戶學習成本高、缺少殺手級應用、如何遷移等等這些現實性的問題。
不過依靠良好的社區和技術先驅,隨著時間的變遷,這些短板也會逐步補齊,真正適應當前時代的技術一定會脫穎而出。
文章來源:https://c1n.cn/J3wve

轉自:幽鬼,侵刪

相關新聞

歷經多年發展,已成為國內好評如潮的Linux云計算運維、SRE、Devops、網絡安全、云原生、Go、Python開發專業人才培訓機構!

    1. 主站蜘蛛池模板: 邓州市| 马边| 泉州市| 棋牌| 高陵县| 从化市| 通江县| 安福县| 囊谦县| 博客| 汾阳市| 浙江省| 舟山市| 利津县| 江口县| 错那县| 南部县| 宾阳县| 延川县| 会东县| 威海市| 桑日县| 海盐县| 乐山市| 茌平县| 民勤县| 北海市| 陆川县| 英吉沙县| 苍南县| 钦州市| 宜宾县| 雷州市| 沾化县| 汪清县| 前郭尔| 银川市| 漳州市| 江北区| 嘉兴市| 巫溪县|