<ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>


      實戰(zhàn)前言
      RabbitMQ
      作為目前應(yīng)用相當(dāng)廣泛的消息中間件,在企業(yè)級應(yīng)用、微服務(wù)應(yīng)用中充當(dāng)著重要的角色。特別是在一些典型的應(yīng)用場景以及業(yè)務(wù)模塊中具有重要的作用,比如業(yè)務(wù)服務(wù)模塊解耦、異步通信、高并發(fā)限流、超時業(yè)務(wù)、數(shù)據(jù)延遲處理等。上篇博文我介紹分享了RabbitMQ在業(yè)務(wù)服務(wù)模塊異步解耦以及通信的實戰(zhàn)業(yè)務(wù)場景,感興趣童鞋可以前往觀看:
      https://www.roncoo.com/article/detail/134309
      <https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.roncoo.com%2Farticle%2Fdetail%2F134309>

      這邊博文我們繼續(xù)介紹分享RabbitMQ消息確認(rèn)機(jī)制以及并發(fā)量的配置,并介紹分享其在高并發(fā)系統(tǒng)場景下的實戰(zhàn)!

      RabbitMQ 實戰(zhàn):并發(fā)量配置與消息確認(rèn)機(jī)制

      實戰(zhàn)背景
      對于消息模型中的 listener 而言,默認(rèn)情況下是“單消費實例”的配置,即“一個 listener
      對應(yīng)一個消費者”,這種配置對于上面所講的“異步記錄用戶操作日志”、“異步發(fā)送郵件”等并發(fā)量不高的場景下是適用的。但是在對于秒殺系統(tǒng)、商城搶單等場景下可能會顯得很吃力!

      我們都知道,秒殺系統(tǒng)跟商城搶單均有一個共同的明顯的特征,即在某個時刻會有成百上千萬的請求到達(dá)我們的接口,即瞬間這股巨大的流量將涌入我們的系統(tǒng),我們可以采用下面一圖來大致體現(xiàn)這一現(xiàn)象:

      當(dāng)?shù)搅恕伴_始秒殺”、“開始搶單”的時刻,此時系統(tǒng)可能會出現(xiàn)這樣的幾種現(xiàn)象:

      應(yīng)用系統(tǒng)配置承載不了這股瞬間流量,導(dǎo)致系統(tǒng)直接掛掉,即傳說中的“宕機(jī)”現(xiàn)象;

      接口邏輯沒有考慮并發(fā)情況,數(shù)據(jù)庫讀寫鎖發(fā)生沖突,導(dǎo)致最終處理結(jié)果跟理論上的結(jié)果數(shù)據(jù)不一致(如商品存庫量只有
      100,但是高并發(fā)情況下,實際表記錄的搶到的用戶記錄數(shù)據(jù)量卻遠(yuǎn)遠(yuǎn)大于 100);

      應(yīng)用占據(jù)服務(wù)器的資源直接飆高,如 CPU、內(nèi)存、寬帶等瞬間直接飆升,導(dǎo)致同庫同表甚至可能同 host 的其他服務(wù)或者系統(tǒng)出現(xiàn)卡頓或者掛掉的現(xiàn)象;

      于是乎,我們需要尋找解決方案!對于目前來講,網(wǎng)上均有諸多比較不錯的解決方案,在此我順便提一下我們的應(yīng)用系統(tǒng)采用的常用解決方案,包括:

      我們會將處理搶單的整體業(yè)務(wù)邏輯獨立、服務(wù)化并做集群部署;
      我們會將那股巨大的流量拒在系統(tǒng)的上層,即將其轉(zhuǎn)移至 MQ
      而不直接涌入我們的接口,從而減少數(shù)據(jù)庫讀寫鎖沖突的發(fā)生以及由于接口邏輯的復(fù)雜出現(xiàn)線程堵塞而導(dǎo)致應(yīng)用占據(jù)服務(wù)器資源飆升;

      我們會將搶單業(yè)務(wù)所在系統(tǒng)的其他同數(shù)據(jù)源甚至同表的業(yè)務(wù)拆分獨立出去服務(wù)化,并基于某種 RPC 協(xié)議走 HTTP 通信進(jìn)行數(shù)據(jù)交互、服務(wù)通信等等;

      采用分布式鎖解決同一時間同個手機(jī)號、同一時間同個 IP 刷單的現(xiàn)象;

      下面,我們用 RabbitMQ 來實戰(zhàn)上述的第二點!即我們會在“請求” -> "處理搶單業(yè)務(wù)的接口"
      中間架一層消息中間件做“緩沖”、“緩壓”處理,如下圖所示:

      并發(fā)量配置與消息確認(rèn)機(jī)制
      正如上面所講的,對于搶單、秒殺等高并發(fā)系統(tǒng)而言,如果我們需要用 RabbitMQ 在 “請求” - “接口” 之間充當(dāng)限流緩壓的角色,那便需要我們對
      RabbitMQ 提出更高的要求,即支持高并發(fā)的配置,在這里我們需要明確一點,“并發(fā)消費者”的配置其實是針對 listener 而言,當(dāng)配置成功后,我們可以在
      MQ 的后端控制臺應(yīng)用看到 consumers 的數(shù)量,如下所示:

      其中,這個 listener 在這里有 10 個 consumer 實例的配置,每個 consumer 可以預(yù)監(jiān)聽消費拉取的消息數(shù)量為 5
      個(如果同一時間處理不完,會將其緩存在 mq 的客戶端等待處理?。?br>
      另外,對于某些消息而言,我們有時候需要嚴(yán)格的知道消息是否已經(jīng)被 consumer
      監(jiān)聽消費處理了,即我們有一種消息確認(rèn)機(jī)制來保證我們的消息是否已經(jīng)真正的被消費處理。在 RabbitMQ 中,消息確認(rèn)處理機(jī)制有三種:Auto -
      自動、Manual - 手動、None - 無需確認(rèn),而確認(rèn)機(jī)制需要 listener 實現(xiàn) ChannelAwareMessageListener
      接口,并重寫其中的確認(rèn)消費邏輯。在這里我們將用 “手動確認(rèn)” 的機(jī)制來實戰(zhàn)用戶商城搶單場景。

      1.在 RabbitMQConfig 中配置確認(rèn)消費機(jī)制以及并發(fā)量的配置

      2.消息模型的配置信息

      3.RabbitMQ 后端控制臺應(yīng)用查看此隊列的并發(fā)量配置

      4.listener 確認(rèn)消費處理邏輯:在這里我們需要開發(fā)搶單的業(yè)務(wù)邏輯,即“只有當(dāng)該商品的庫存 >0
      時,搶單成功,扣減庫存量,并將該搶單的用戶信息記錄入表,異步通知用戶搶單成功!”


      5.緊接著我們采用 CountDownLatch 模擬產(chǎn)生高并發(fā)時的多線程請求(或者采用 jmeter
      實施壓測也可以?。總€請求將攜帶產(chǎn)生的隨機(jī)數(shù):充當(dāng)手機(jī)號 -> 充當(dāng)消息,最終入搶單隊列!在這里,我模擬了 50000 個請求,相當(dāng)于 50000
      手機(jī)號同一時間發(fā)生搶單的請求,而設(shè)置的產(chǎn)品庫存量為 100,這在 product 數(shù)據(jù)庫表即可設(shè)置

      6.將搶單請求的手機(jī)號信息壓入隊列,等待排隊處理

      7.在最后我們寫個 Junit 或者寫個 Controller,進(jìn)行 initService.generateMultiThread();
      調(diào)用模擬產(chǎn)生高并發(fā)的搶單請求即可
      @RestController public class ConcurrencyController { private static final
      Logger log= LoggerFactory.getLogger(HelloWorldController.class); private static
      final String Prefix="concurrency"; @Autowired private InitService initService;
      @RequestMapping(value = Prefix+"/robbing/thread",method = RequestMethod.GET)
      public BaseResponse robbingThread(){ BaseResponse response=new
      BaseResponse(StatusCode.Success); initService.generateMultiThread(); return
      response; }}
      8.最后,我們當(dāng)然是跑起來,在控制臺我們可以觀察到系統(tǒng)不斷的在產(chǎn)生新的請求(線程)– 相當(dāng)于不斷的有搶單的手機(jī)號涌入我們的系統(tǒng),然后入隊列,listener
      監(jiān)聽到請求之后消費處理搶單邏輯!最后我們可以觀察兩張數(shù)據(jù)庫表:商品庫存表、商品成功搶單的用戶記錄表 - 只有當(dāng)庫存表中商品對應(yīng)的庫存量為
      0、商品成功搶單的用戶記錄剛好 100 時 即表示我們的實戰(zhàn)目的以及效果已經(jīng)達(dá)到了??!

      總結(jié):如此一來,我們便將 request 轉(zhuǎn)移到我們的
      mq,在一定程度緩解了我們的應(yīng)用以及接口的壓力!當(dāng)然,實際情況下,我們的配置可能遠(yuǎn)遠(yuǎn)不只代碼層次上的配置,比如我們的 mq
      可能會做集群配置、負(fù)載均衡、商品庫存的更新可能會考慮分庫分表、庫存更新可能會考慮獨立為庫存 Dubbo 服務(wù)并通過 Rest Api
      異步通信交互并獨立部署等等。這些優(yōu)化以及改進(jìn)的目的其實無非是為了能限流、緩壓、保證系統(tǒng)穩(wěn)定、數(shù)據(jù)的一致等!而我們的
      MQ,在其中可以起到不可磨滅的作用,其字如其名:“消息隊列”,而隊列具有 “先進(jìn)先出” 的特點,故而所有進(jìn)入 MQ 的消息都將 “乖巧” 的在 MQ
      上排好隊,先來先排隊,先來先被處理消費,由此一來至少可以避免 “瞬間時刻一窩蜂的 request 涌入我們的接口” 的情況!

      附注:在用 RabbitMQ
      實戰(zhàn)上述高并發(fā)搶單解決方案,其實我也在數(shù)據(jù)庫層面進(jìn)行了優(yōu)化,即在讀寫存庫時采用了“類似樂觀鎖”的寫法,保證:搶單的請求到來時有庫存,更新存庫時保證有庫存可以被更新!


      彩蛋:本博文繼續(xù)分享介紹了RabbitMQ典型應(yīng)用業(yè)務(wù)場景的實戰(zhàn)-并發(fā)系統(tǒng)下RabbitMQ的限流作用以及基于SpringBoot微服務(wù)項目的實戰(zhàn),另外也介紹了消息確認(rèn)機(jī)制的配置實戰(zhàn)跟并發(fā)量配置,下篇博文將繼續(xù)分享死信隊列的相關(guān)內(nèi)容及其實戰(zhàn)。另外,博主已將RabbitMQ相關(guān)技術(shù)以及場景實戰(zhàn)的相關(guān)要點錄制成了視頻教程。

      感興趣小伙伴可以前往學(xué)習(xí)觀看:SpringBoot整合RabbitMQ實戰(zhàn)
      <https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.roncoo.com%2Fcourse%2Fview%2F95ffac8bd3aa4f2d8a0d83c32f46c69d>

      友情鏈接
      ioDraw流程圖
      API參考文檔
      OK工具箱
      云服務(wù)器優(yōu)惠
      阿里云優(yōu)惠券
      騰訊云優(yōu)惠券
      京東云優(yōu)惠券
      站點信息
      問題反饋
      郵箱:[email protected]
      QQ群:637538335
      關(guān)注微信

        <ul id="qxxfc"><fieldset id="qxxfc"><tr id="qxxfc"></tr></fieldset></ul>
          女技师三级做爰按摩电影 | www.草逼网站 | 国产精品不卡在线 | 丰满少妇双乳被呻吟进入 | 性生活免费视频 | 爱操视频网| 亚洲欧美伦理在线 | 抽插日韩 | 中国操逼网 | 羞羞漫画黄漫免费观看 |