spring cloud 介紹
spring cloud 是一系列框架的集合。它利用 spring boot 的開發便利性巧妙地簡化了分布式系統基礎設施的開發,如服務發現注冊、配置中心、消息總線、負載均衡、斷路器、數據監控等,都可以用 spring boot 的開發風格做到一鍵啟動和部署。spring cloud 並沒有重復制造輪子,它只是將目前各家公司開發的比較成熟、經得起實際考驗的服務框架組合起來,通過 spring boot 風格進行再封裝屏蔽掉了復雜的配置和實現原理,最終給開發者留出了一套簡單易懂、易部署和易維護的分布式系統開發工具包。
spring cloud 對於中小型互聯網公司來說是一種福音,因為這類公司往往沒有實力或者沒有足夠的資金投入去開發自己的分布式系統基礎設施,使用 spring cloud 一站式解決方案能在從容應對業務發展的同時大大減少開發成本。同時,隨着近幾年微服務架構和 docker 容器概念的火爆,也會讓 spring cloud 在未來越來越“雲”化的軟件開發風格中立有一席之地,尤其是在目前五花八門的分布式解決方案中提供了標准化的、一站式的技術方案,意義可能會堪比當年 servlet 規范的誕生,有效推進服務端軟件系統技術水平的進步。
spring cloud 技術組成
eureka:微服務治理,服務注冊和發現
ribbon:負載均衡、請求重試
hystrix:斷路器,服務降級、熔斷
feign:ribbon + hystrix 集成,並提供生命式客戶端
hystrix dashboard 和 turbine:hystrix 微服務監控
zuul:API 網關,提供微服務的統一入口,並提供統一的權限驗證
config:配置中心
bus:配置更新消息總線
sleuth:鏈路追蹤
2.1 eureka注冊中心
與zookeeper 類似,維護一組微服務的地址信息
Zookeeper:某一個微服務不可用,會立即刪除該服務的注冊信息
eureka:某一個微服務不可用,會保護該服務的注冊信息,不刪除
eureka的設計值認為,服務不可用可能不是服務本身的問題,只是由於微服務和注冊中心之間的網絡問題,而與其他微服務之間可能仍然可以連接
netflix公司開發的一套微服務框架,並開源,spring cloud集成了netflix 的微服務框架:
eureka
ribbon
hystrix
feign
zuul
客戶端每30秒向eureka服務器發送信條數據
如果一個客戶端90秒內沒有發送心跳數據,認為該服務不可用
客戶端每隔30秒,從eureka拉取新的注冊信息
2.2 ribbon
作用: 負載均衡和重試
封裝 RestTemplate,生成動態代理,來添加負載均衡和重試的代碼
單獨使用ribbon,開啟重試需要自己寫代碼,添加重試參數配置
后面 ribbon 被feign 和 zuul 封裝,不做任何配置,不寫任何代碼,可以直接使用負載均衡和重試
2.3 hystrix
斷路器,降級和熔斷
降級:
當服務不可用,或者訪問超時,可以執行降級代碼,可以返回錯誤信息,或者返回緩存數據
熔斷:
10秒內請求數量達到20個,並且,有50% 出現失敗降級的情況,會打開斷路器,所有的請求,都直接降級,不再向后台微服務轉發
斷路器打開5秒后,會處於半開狀態,當請求到達時,會嘗試向后台符轉發,如果成功,會關閉斷路器,如果仍然失敗,保持打開狀態
2.4 feign
聲明式客戶端、整合 ribbon 和 hystrix
feign整合ribbon
不需要任何配置,已經啟用ribbon的負載均衡和重試
feign整合 hystrix
啟用 hystrix
feign.hystrix.enabled=true
添加 hystrix 依賴
暴露 hystrix.stream 監控端點
2.5 zuul
作用:api網關,路由,負載均衡等多種作用
簡介:類似nginx,反向代理的功能,不過netflix自己增加了一些配合其他組件的特性。
在微服務架構中,后端服務往往不直接開放給調用端,而是通過一個API網關根據請求的url,路由到相應的服務。當添加API網關后,在第三方調用端和服務提供方之間就創建了一面牆,這面牆直接與調用方通信進行權限控制,后將請求均衡分發給后台服務端。
過濾器權限過濾:繼承 ZuulFilter
降級:實現 FallbackProvider
2.5 config
作用:配置管理
簡介:SpringCloud Config提供服務器端和客戶端。服務器存儲后端的默認實現使用git,因此它輕松支持標簽版本的配置環境,以及可以訪問用於管理內容的各種工具。
3、常見面試題
問題一:什么是Spring Cloud?
Spring cloud流應用程序啟動器是基於Spring Boot的Spring集成應用程序,提供與外部系統的集成。Spring cloud Task,一個生命周期短暫的微服務框架,用於快速構建執行有限數據處理的應用程序。
問題二:使用Spring Cloud有什么優勢?
使用Spring Boot開發分布式微服務時,我們面臨以下問題
1、與分布式系統相關的復雜性-這種開銷包括網絡問題,延遲開銷,帶寬問題,安全問題。
2、服務發現-服務發現工具管理群集中的流程和服務如何查找和互相交談。它涉及一個服務目錄,在該目錄中注冊服務,然后能夠查找並連接到該目錄中的服務。
3、冗余-分布式系統中的冗余問題。
4、負載平衡 --負載平衡改善跨多個計算資源的工作負荷,諸如計算機,計算機5、集群,網絡鏈路,中央處理單元,或磁盤驅動器的分布。
6、性能-問題 由於各種運營開銷導致的性能問題。
7、部署復雜性-Devops技能的要求。
優點:
1.Spring Cloud 來源於 Spring,質量、穩定性、持續性都可以得到保證。
2.Spirng Cloud 天然支持 Spring Boot,更加便於業務落地。
3.Spring Cloud 發展非常的快,從 2016 年開始接觸的時候相關組件版本為 1.x,到現在將要發布 2.x 系列。
4.Spring Cloud 是 Java 領域最適合做微服務的框架。
5.相比於其它框架,Spring Cloud 對微服務周邊環境的支持力度最大。
6.對於中小企業來講,使用門檻較低。
7.Spring Cloud 是微服務架構的最佳落地方案
問題三:服務注冊和發現是什么意思?Spring Cloud如何實現?
當我們開始一個項目時,我們通常在屬性文件中進行所有的配置。隨着越來越多的服務開發和部署,添加和修改這些屬性變得更加復雜。有些服務可能會下降,而某些位置可能會發生變化。手動更改屬性可能會產生問題。 Eureka服務注冊和發現可以在這種情況下提供幫助。由於所有服務都在Eureka服務器上注冊並通過調用Eureka服務器完成查找,因此無需處理服務地點的任何更改和處理。
問題四:負載均衡的意義什么?
在計算中,負載平衡可以改善跨計算機,計算機集群,網絡鏈接,中央處理單元或磁盤驅動器等多種計算資源的工作負載分布。負載平衡旨在優化資源使用,最大化吞吐量,最小化響應時間並避免任何單一資源的過載。使用多個組件進行負載平衡而不是單個組件可能會通過冗余來提高可靠性和可用性。負載平衡通常涉及專用軟件或硬件,例如多層交換機或域名系統服務器進程。
問題五:什么是Hystrix?它如何實現容錯?
Hystrix是一個延遲和容錯庫,旨在隔離遠程系統,服務和第三方庫的訪問點,當出現故障是不可避免的故障時,停止級聯故障並在復雜的分布式系統中實現彈性。
通常對於使用微服務架構開發的系統,涉及到許多微服務。這些微服務彼此協作。
問題六:什么是Hystrix斷路器?我們需要它嗎?
由於某些原因,employee-consumer公開服務會引發異常。在這種情況下使用Hystrix我們定義了一個回退方法。如果在公開服務中發生異常,則回退方法返回一些默認值。如果firstPage method() 中的異常繼續發生,則Hystrix電路將中斷,並且員工使用者將一起跳過firtsPage方法,並直接調用回退方法。 斷路器的目的是給第一頁方法或第一頁方法可能調用的其他方法留出時間,並導致異常恢復。可能發生的情況是,在負載較小的情況下,導致異常的問題有更好的恢復機會
4、solr-lucene
4.1 solr概念
Solr是一個高性能,基於Lucene的全文搜索服務器。同時對其進行了擴展,提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴展,並對查詢性能進行了優化,並且提供了一個完善的功能管理界面,是一款非常優秀的全文搜索引擎。
4.2 lucene概念
Lucene是apache jakarta項目的一個子項目,是一個開放源代碼的全文檢索引擎開發工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎。Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。
4.3 倒排索引
Mysql索引是(B+tree)
我們一般情況下,先找到文檔,再在文檔中找出包含的詞;
倒排索引則是這個過程反過來,用詞,來找出它出現的文檔.
實際舉例
文檔編號 文檔內容
1、全文檢索引擎工具包
2、全文檢索引擎的架構
3、查詢引擎和索引引擎
分詞結果
文檔編號 分詞結果集
1、{全文,檢索,引擎,工具,包}
2、{全文,檢索,引擎,的,架構}
3、{查詢,引擎,和,索引,引擎}
5、rabbitMQ
5.1 概念
MQ全稱是Message Queue,可以理解為消息隊列的意思,簡單來說就是消息以管道的方式進行傳遞。RabbitMQ是一個實現了AMQP(Advanced Message Queuing Protocol)高級消息隊列協議的消息隊列服務,用Erlang語言的。
RabbitMQ是一種消息中間件,用於處理來自客戶端的異步消息。服務端將要發送的消息放入到隊列池中。接收端可以根據RabbitMQ配置的轉發機制接收服務端發來的消息。RabbitMQ依據指定的轉發規則進行消息的轉發、緩沖和持久化操作,主要用在多服務器間或單服務器的子系統間進行通信,是分布式系統標准的配置。
為什么選擇RabbitMQ
現在的市面上有很多MQ可以選擇,比如ActiveMQ、ZeroMQ、Appche Qpid,那問題來了為什么要選擇RabbitMQ?
1、除了Qpid,RabbitMQ是唯一一個實現了AMQP標准的消息服務器;
2、可靠性,RabbitMQ的持久化支持,保證了消息的穩定性;
3、高並發,RabbitMQ使用了Erlang開發語言,Erlang是為電話交換機開發的語言,天生自帶高並發光環,和高可用特性;
4、集群部署簡單,正是應為Erlang使得RabbitMQ集群部署變的超級簡單;
5、社區活躍度高,根據網上資料來看,RabbitMQ也是首選;
5.2 工作模式
5.2.1 簡單模式
RabbitMQ是一個消息中間件,你可以想象它是一個郵局。當你把信件放到郵箱里時,能夠確信郵遞員會正確地遞送你的信件。RabbitMq就是一個郵箱、一個郵局和一個郵遞員。
發送消息的程序是生產者
隊列就代表一個郵箱。雖然消息會流經RbbitMQ和你的應用程序,但消息只能被存儲在隊列里。隊列存儲空間只受服務器內存和磁盤限制,它本質上是一個大的消息緩沖區。多個生產者可以向同一個隊列發送消息,多個消費者也可以從同一個隊列接收消息.
消費者等待從隊列接收消息
5.2.2 工作模式
工作隊列(即任務隊列)背后的主要思想是避免立即執行資源密集型任務,並且必須等待它完成。相反,我們將任務安排在稍后完成。
我們將任務封裝為消息並將其發送到隊列。后台運行的工作進程將獲取任務並最終執行任務。當運行多個消費者時,任務將在它們之間分發。
使用任務隊列的一個優點是能夠輕松地並行工作。如果我們正在積壓工作任務,我們可以添加更多工作進程,這樣就可以輕松擴展。
一個生產者,多個消費者,每個消費者獲取到的消息唯一。
1、 自動模式
消費者從消息隊列獲取消息后,服務端就認為該消息已經成功消費。
2、 手動模式
消費者從消息隊列獲取消息后,服務端並沒有標記為成功消費
消費者成功消費后需要將狀態返回到服務端
5.2.3 發布訂閱模式
一個生產者發送的消息會被多個消費者獲取。
生產者:可以將消息發送到隊列或者是交換機。
消費者:只能從隊列中獲取消息。
如果消息發送到沒有隊列綁定的交換機上,那么消息將丟失。
Exchanges 交換機(使用fanout交換機)
RabbitMQ消息傳遞模型的核心思想是,生產者永遠不會將任何消息直接發送到隊列。實際上,通常生產者甚至不知道消息是否會被傳遞到任何隊列。
相反,生產者只能向交換機(Exchange)發送消息。交換機是一個非常簡單的東西。一邊接收來自生產者的消息,另一邊將消息推送到隊列。交換器必須確切地知道如何處理它接收到的消息。它應該被添加到一個特定的隊列中嗎?它應該添加到多個隊列中嗎?或者它應該被丟棄。這些規則由exchange的類型定義。
有幾種可用的交換類型:direct、topic、header和fanout。我們將關注最后一個——fanout。讓我們創建一個這種類型的交換機,並稱之為 logs: ch.exchangeDeclare("logs", "fanout");
fanout交換機非常簡單。它只是將接收到的所有消息廣播給它所知道的所有隊列。這正是我們的日志系統所需要的。
5.2.4 路由模式
1、發送消息到交換機並且要指定路由key
2、 消費者將隊列綁定到交換機時需要指定路由key
使用直連交換機 Direct exchange
如果將日志消息寫入磁盤的程序只接收關鍵error,而不是在warning或info日志消息上浪費磁盤空間。
前面我們使用的是fanout交換機,這並沒有給我們太多的靈活性——它只能進行簡單的廣播。
我們將用直連交換機(Direct exchange)代替。它背后的路由算法很簡單——消息傳遞到bindingKey與routingKey完全匹配的隊列。
5.2.5 主題模式
在上一小節,我們改進了日志系統。我們沒有使用只能進行廣播的fanout交換機,而是使用Direct交換機,從而可以選擇性接收日志。
雖然使用Direct交換機改進了我們的系統,但它仍然有局限性——它不能基於多個標准進行路由。
在我們的日志系統中,我們可能不僅希望根據級別訂閱日志,還希望根據發出日志的源訂閱日志。
這將給我們帶來很大的靈活性——我們可能只想接收來自“cron”的關鍵錯誤,但也要接收來自“kern”的所有日志。
要在日志系統中實現這一點,我們需要了解更復雜的Topic交換機。
主題交換機 Topic exchange
發送到Topic交換機的消息,它的的routingKey,必須是由點分隔的多個單詞。單詞可以是任何東西,但通常是與消息相關的一些特性。幾個有效的routingKey示例:“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”。routingKey可以有任意多的單詞,最多255個字節。
bindingKey也必須采用相同的形式。Topic交換機的邏輯與直連交換機類似——使用特定routingKey發送的消息將被傳遞到所有使用匹配bindingKey綁定的隊列。bindingKey有兩個重要的特殊點:
* 可以通配單個單詞。
# 可以通配零個或多個單詞。
5.2.6 RPC模式
(RPC) Remote Procedure Call Protocol 遠程過程調用協議
在一個大型的公司,系統由大大小小的服務構成,不同的團隊維護不同的代碼,部署在不同的機器。但是在做開發時候往往要用到其它團隊的方法,因為已經有了實現。但是這些服務部署不同的機器上,想要調用就需要網絡通信,這些代碼繁瑣且復雜,一不小心就會寫的很低效。RPC協議定義了規划,其它的公司都給出了不同的實現。比如微軟的wcf,以及現在火熱的WebApi。
回調隊列 Callback Queue
使用RabbitMQ去實現RPC很容易。一個客戶端發送請求信息,並得到一個服務器端回復的響應信息。為了得到響應信息,我們需要在請求的時候發送一個“回調”隊列地址。我們可以使用默認隊列。
關聯id (correlationId):
在上面的代碼中,我們會為每個RPC請求創建一個回調隊列。 這是非常低效的,這里還有一個更好的方法:讓我們為每個客戶端創建一個回調隊列。
這就提出了一個新的問題,在隊列中得到一個響應時,我們不清楚這個響應所對應的是哪一條請求。這時候就需要使用關聯id(correlationId)。我們將為每一條請求設置唯一的的id值。稍后,當我們在回調隊列里收到一條消息的時候,我們將查看它的id屬性,這樣我們就可以匹配對應的請求和響應。如果我們發現了一個未知的id值,我們可以安全的丟棄這條消息,因為它不屬於我們的請求。
RPC的工作方式是這樣的:
對於RPC請求,客戶端發送一條帶有兩個屬性的消息:replyTo,設置為僅為請求創建的匿名獨占隊列,和correlationId,設置為每個請求的惟一id值。
請求被發送到rpc_queue隊列。
RPC工作進程(即:服務器)在隊列上等待請求。當一個請求出現時,它執行任務,並使用replyTo字段中的隊列將結果發回客戶機。
客戶機在回應消息隊列上等待數據。當消息出現時,它檢查correlationId屬性。如果匹配請求中的值,則向程序返回該響應數據。
5.3 其他
ConnectionFactory(連接管理器)、Channel(信道)、Exchange(交換器)、Queue(隊列)、RoutingKey(路由鍵)、BindingKey(綁定鍵)。
ConnectionFactory(連接管理器):應用程序與Rabbit之間建立連接的管理器,程序代碼中使用;
Channel(信道):消息推送使用的通道;
Exchange(交換器):用於接受、分配消息;
Queue(隊列):用於存儲生產者的消息;
RoutingKey(路由鍵):用於把生成者的數據分配到交換器上;
BindingKey(綁定鍵):用於把交換器的消息綁定到隊列上;
5.3.1 消息持久化
Rabbit隊列和交換器有一個不可告人的秘密,就是默認情況下重啟服務器會導致消息丟失,那么怎么保證Rabbit在重啟的時候不丟失呢?答案就是消息持久化。
當你把消息發送到Rabbit服務器的時候,你需要選擇你是否要進行持久化,但這並不能保證Rabbit能從崩潰中恢復,想要Rabbit消息能恢復必須滿足3個條件:
1、投遞消息的時候durable設置為true,消息持久化,代碼:channel.queueDeclare(x, true, false, false, null),參數2設置為true持久化;
2、設置投遞模式deliveryMode設置為2(持久),代碼:channel.basicPublish(x, x, MessageProperties.PERSISTENT_TEXT_PLAIN,x),參數3設置為存儲純文本到磁盤;
3、消息已經到達持久化交換器上;
4、消息已經到達持久化的隊列;
持久化工作原理
Rabbit會將你的持久化消息寫入磁盤上的持久化日志文件,等消息被消費之后,Rabbit會把這條消息標識為等待垃圾回收。
持久化的缺點
消息持久化的優點顯而易見,但缺點也很明顯,那就是性能,因為要寫入硬盤要比寫入內存性能較低很多,從而降低了服務器的吞吐量,盡管使用SSD硬盤可以使事情得到緩解,但他仍然吸干了Rabbit的性能,當消息成千上萬條要寫入磁盤的時候,性能是很低的。
所以使用者要根據自己的情況,選擇適合自己的方式。
5.4 常見面試題
1.什么是rabbitmq
采用AMQP高級消息隊列協議的一種消息隊列技術,最大的特點就是消費並不需要確保提供方存在,實現了服務之間的高度解耦
2.為什么要使用rabbitmq
1.在分布式系統下具備異步,削峰,負載均衡等一系列高級功能;
2.擁有持久化的機制,進程消息,隊列中的信息也可以保存下來。
3.實現消費者和生產者之間的解耦。
4.對於高並發場景下,利用消息隊列可以使得同步訪問變為串行訪問達到一定量的限流,利於數據庫的操作。
5.可以使用消息隊列達到異步下單的效果,排隊中,后台進行邏輯下單。
3.使用rabbitmq的場景
1.服務間異步通信
2.順序消費
3.定時任務
4.請求削峰
4.如何確保消息正確地發送至RabbitMQ? 如何確保消息接收方消費了消息?
發送方確認模式
將信道設置成confirm模式(發送方確認模式),則所有在信道上發布的消息都會被指派一個唯一的ID。
一旦消息被投遞到目的隊列后,或者消息被寫入磁盤后(可持久化的消息),信道會發送一個確認給生產者(包含消息唯一ID)。
如果RabbitMQ發生內部錯誤從而導致消息丟失,會發送一條nack(not acknowledged,未確認)消息。
發送方確認模式是異步的,生產者應用程序在等待確認的同時,可以繼續發送消息。當確認消息到達生產者應用程序,生產者應用程序的回調方法就會被觸發來處理確認消息。
接收方確認機制
接收方消息確認機制:消費者接收每一條消息后都必須進行確認(消息接收和消息確認是兩個不同操作)。只有消費者確認了消息,RabbitMQ才能安全地把消息從隊列中刪除。
這里並沒有用到超時機制,RabbitMQ僅通過Consumer的連接中斷來確認是否需要重新發送消息。也就是說,只要連接不中斷,RabbitMQ給了Consumer足夠長的時間來處理消息。保證數據的最終一致性;
下面羅列幾種特殊情況:
如果消費者接收到消息,在確認之前斷開了連接或取消訂閱,RabbitMQ會認為消息沒有被分發,然后重新分發給下一個訂閱的消費者。(可能存在消息重復消費的隱患,需要去重)
如果消費者接收到消息卻沒有確認消息,連接也未斷開,則RabbitMQ認為該消費者繁忙,將不會給該消費者分發更多的消息。
5.如何避免消息重復投遞或重復消費?
在消息生產時,MQ內部針對每條生產者發送的消息生成一個inner-msg-id,作為去重的依據(消息投遞失敗並重傳),避免重復的消息進入隊列;
在消息消費時,要求消息體中必須要有一個bizId(對於同一業務全局唯一,如支付ID、訂單ID、帖子ID等)作為去重的依據,避免同一條消息被重復消費。
6.消息基於什么傳輸?
由於TCP連接的創建和銷毀開銷較大,且並發數受系統資源限制,會造成性能瓶頸。RabbitMQ使用信道的方式來傳輸數據。信道是建立在真實的TCP連接內的虛擬連接,且每條TCP連接上的信道數量沒有限制。
7.消息如何分發?
若該隊列至少有一個消費者訂閱,消息將以循環(round-robin)的方式發送給消費者。每條消息只會分發給一個訂閱的消費者(前提是消費者能夠正常處理消息並進行確認)。
通過路由可實現多消費的功能
8.消息怎么路由?
消息提供方->路由->一至多個隊列
消息發布到交換器時,消息將擁有一個路由鍵(routing key),在消息創建時設定。
通過隊列路由鍵,可以把隊列綁定到交換器上。
消息到達交換器后,RabbitMQ會將消息的路由鍵與隊列的路由鍵進行匹配(針對不同的交換器有不同的路由規則);
常用的交換器主要分為一下三種:
fanout:如果交換器收到消息,將會廣播到所有綁定的隊列上
direct:如果路由鍵完全匹配,消息就被投遞到相應的隊列
topic:可以使來自不同源頭的消息能夠到達同一個隊列。 使用topic交換器時,可以使用通配符
9.如何確保消息不丟失?
消息持久化,當然前提是隊列必須持久化
RabbitMQ確保持久性消息能從服務器重啟中恢復的方式是,將它們寫入磁盤上的一個持久化日志文件,當發布一條持久性消息到持久交換器上時,Rabbit會在消息提交到日志文件后才發送響應。
一旦消費者從持久隊列中消費了一條持久化消息,RabbitMQ會在持久化日志中把這條消息標記為等待垃圾收集。如果持久化消息在被消費之前RabbitMQ重啟,那么Rabbit會自動重建交換器和隊列(以及綁定),並重新發布持久化日志文件中的消息到合適的隊列。
10.使用RabbitMQ有什么好處?
服務間高度解耦,
異步通信性能高,
流量削峰
11.rabbitmq的集群
鏡像集群模式
你創建的queue,無論元數據還是queue里的消息都會存在於多個實例上,然后每次你寫消息到queue的時候,都會自動把消息到多個實例的queue里進行消息同步。
好處在於,你任何一個機器宕機了,沒事兒,別的機器都可以用。壞處在於,第一,這個性能開銷也太大了吧,消息同步所有機器,導致網絡帶寬壓力和消耗很重!第二,這么玩兒,就沒有擴展性可言了,如果某個queue負載很重,你加機器,新增的機器也包含了這個queue的所有數據,並沒有辦法線性擴展你的queue
12.mq的缺點
系統可用性降低
系統引入的外部依賴越多,越容易掛掉,本來你就是A系統調用BCD三個系統的接口就好了,人ABCD四個系統好好的,沒啥問題,你偏加個MQ進來,萬一MQ掛了咋整?MQ掛了,整套系統崩潰了,你不就完了么。
系統復雜性提高
硬生生加個MQ進來,你怎么保證消息沒有重復消費?怎么處理消息丟失的情況?怎么保證消息傳遞的順序性?頭大頭大,問題一大堆,痛苦不已
一致性問題
A系統處理完了直接返回成功了,人都以為你這個請求就成功了;但是問題是,要是BCD三個系統那里,BD兩個系統寫庫成功了,結果C系統寫庫失敗了,咋整?你這數據就不一致了。