1. 程式人生 > >結合生活案例實現rabbitmq訊息通訊

結合生活案例實現rabbitmq訊息通訊

ps : 這篇文章比較長,讀者還是需要耐心的閱讀的。乾貨多多。

在分散式專案中為了提高效能,也為了實現專案規範,我們都會在處理訊息佇列的時候引入訊息中介軟體。中介軟體的作用一個是為了解耦,還有一個是效能提升。訊息中介軟體我們每個人每天都在接觸,相信大家都用過美團或者是聽過美團。從程式設計師的角度看美團外賣涉及三方角色。【商家】【騎手】【顧客】。這三者的關係簡單理解如下

下面案例會通過程式碼說明,如下是專案結構

rabbit-demo

下訂單

今天我們著重介紹下訂單的流程,那為什麼選擇下訂單流程而不選擇其他兩個流程呢。因為派送流程不是訊息佇列。如果非要規劃為訊息塊我只能認為是訊息消費。而發訂單呢流程和下訂單是一樣的。考慮讀者應該都是平時點餐的那位。對下訂單應該更加的瞭解。

線下買單

我們想想在美團外賣推出之前我們點餐的過程。是顧客到商家店鋪裡進行買單消費的。這種模式存在什麼弊端。這就必須商家的店鋪夠大,人手夠多才能夠讓我們消費者不擁堵起來。但是這樣就增加了商家的成本。所以在這種侷限的條件下我們的線上交易誕生了。

線上交易

有了美團我們就只需要在手機點餐,商家就會進行選擇行接受,然後出貨。這就是下單的一個流程。後面的就是騎手商家流程了。

我們的顧客相當於是在向訊息佇列中新增訊息,訊息體就是我們的訂單。在美團外賣的系統中同一時刻可能多人點單這就導致商家一時間處理不過來,這是我們的mq就作為一中快取機制先將顧客的訂單本地化,mq按先進先出的順序將訊息有條不紊的派發到只能的商家手中。這就解決我們人多導致訂單繁瑣的問題了。

好了以上是我們用mq的好處。下面我們通過程式碼看看mq具體的傳送訊息的集中方式。

mq結構圖

環境準備

rabbitmq安裝

由於RabbitMQ是用Erlang語言編寫的,因此需要先安裝Erlang。

  • 通過http://www.erlang.org/downloads獲取對應安裝檔案進行安裝
  • 增加環境變數ERLANG_HOME=D:\Program Files\erl9.3(這裡的目錄是我的安裝目錄,你要換成自己的目錄)
  • 修改環境變數Path,在原來的值後面加上“;%ERLANG_HOME%\bin”

安裝完Erlang之後,我們就可以安裝RabbitMQ了。

  • 到http://www.rabbitmq.com/install-windows-manual.html下載安裝包進行安裝
  • 增加環境變數RABBITMQ_HOEM=D:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.5(這裡的目錄是我的安裝目錄,你要換成自己的目錄)
  • 修改環境變數Path,在原來的值後面加上“;%RABBITMQ_HOME%\sbin”

安裝好之後,RabbitMQ就作為一個服務按照預設方式進行啟動了

執行命令rabbitmq-plugins enable rabbitmq_management 開啟Web管理外掛

通過瀏覽器訪問http://localhost:15672,並通過預設使用者guest進行登入,密碼也是guest,登入後的頁面:

springboot專案搭建

關於springboot的搭建這裡就不能細說了。我們直接在zxhtom框架中擴充套件了。只要在裡面新增如下依賴就行了


<!-- rabbit mq -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

然後我們只需要建立一個RabbitConfig類。這個類的作用就是讓mq在專案啟動初期檢查並完成各個元件的建立。既然交給spring完成自然需要在類上加上@Configuration註解。

只需要完成以上操作,我們的mq服務就算是配置完成了。剩下的就應該是生產消費了。
這裡比較注意的是RabbitConfig這個類,這個類裡到底是什麼東西,我們在看程式碼前我們先來了解下mq的原理。

rabbitmq元件拆裝

Queue : 訊息佇列 , 生產者的直接接觸物件。
Exchange : 交換機 , 正常情況消費者是直接接觸交換機的。
Routing Key : 生產者和消費者接觸的兩個不同物件。這就需要routing key 將兩者物件進行關聯起來
Binding : 通過routing key進行繫結到一起。

下面是消費者、生產者、佇列、交換機、rk、binding之間的關係

四種交換機

上面我們瞭解了mq的內部結構,其實還是很簡單的。但是我們mq有的時候有廣播模式,有的點對點模式。這些是這麼來的呢。對了正是我們本節介紹的內容--交換機。

Direct Exchange

顧名思義就是【直連交換機】。要求傳送的訊息與一個特定的路由鍵完全的匹配。如下程式碼中我們queue1的佇列和directExchange交換機通過DIRECTION繫結到了一起。那麼我們傳送訊息是必須將訊息標記為DIRECTION


@Bean
public Binding binding1(){
    return BindingBuilder.bind(queue1()).to(directExchange()).with(DIRECTIONKEY);
}

public void directionSend() {
    rabbitTemplate.convertAndSend(RabbitConfig.DIRECTEXCHANGE, "directionKey", msg);
}

Fanout Exchange

fanout中文翻譯為【輸出】,在這裡我們理解成廣播。【廣播交換機】
廣播的意思就是所有人都能接受到,在這裡需要重新定義為只要繫結在次交換機上的所有佇列都能接收到。不想其他交換機需要key來進行暗號匹配。Fanout Exchange就是我們常用的廣播模式,只要訂閱就會收到訊息。像一些房產中介就是這種模式,只要你留下手機號碼樓盤動態就會實時的推送在你的手機上。


@Bean
public Binding fanoutBinding1(){
    return BindingBuilder.bind(queue1()).to(fanoutExchange());
}
@Bean
public Binding fanoutBinding2(){
    return BindingBuilder.bind(queue2()).to(fanoutExchange());
}
@Bean
public Binding fanoutBinding3(){
    return BindingBuilder.bind(queue3()).to(fanoutExchange());
}
@Bean
public Binding fanoutBinding4(){
    return BindingBuilder.bind(queue4()).to(fanoutExchange());
}

下面程式碼就是隻要有訊息傳送到Fanout Exchange上所有的佇列就會收到訊息

public void fanoutSend1() {
    rabbitTemplate.convertAndSend(RabbitConfig.FANOUTEXCHANGE, RabbitConfig.QUEUETHIRD, msg);
}

Topic Exchange

將路由鍵和某種模式進行匹配,這裡可以理解成Direction Exchange裡的key可以通過某種正則匹配
# : 表示一個或多個詞,
* : 表示一個詞
zxh.# : 能夠匹配 zxh ; zxh. ; zxh.abc ; zxh.ab.sd.s.a
zxh.* : 能夠匹配 zxh.test ; zxh.demo

Headers Exchange

不處理路由鍵。而是根據傳送的訊息內容中的headers屬性進行匹配。在繫結Queue與Exchange時指定一組鍵值對;當訊息傳送到RabbitMQ時會取到該訊息的headers與Exchange繫結時指定的鍵值對進行匹配;如果完全匹配則訊息會路由到該佇列,否則不會路由到該佇列。headers屬性是一個鍵值對,可以是Hashtable,鍵值對的值可以是任何型別。而fanout,direct,topic 的路由鍵都需要要字串形式的。

匹配規則x-match有下列兩種型別:

x-match = all :表示所有的鍵值對都匹配才能接受到訊息

x-match = any :表示只要有鍵值對匹配就能接受到訊息

//請求資料中必須符合headerValues中任意一個引數
@Bean
public Binding headBinding1(){
    Map<String,Object> headerValues = new HashMap<>();
    headerValues.put("type", "cash");
    headerValues.put("aging", "fast");
    return BindingBuilder.bind(queue1()).to(headersExchange()).whereAll(headerValues).match();
}

死信佇列

上面四中交換機介紹完了。我們這裡還有一種叫做死信佇列
還是美團外賣為列, 我們平時美團點單完之後,但是不確定是不是現在就要商家制作。這個時候我們就不會選擇下單。美團就會提示我們30分鐘之內完成付款,負責失效。想想也對美團不可能一直在哪裡等著你下單。你這樣會佔用人家記憶體的。


@Bean
public Queue deadLetterQueue(){
    Map<String, Object> arguments = new HashMap<String, Object>();
    //設定此死信佇列訊息過期後,訊息轉發到那個佇列上
    arguments.put("x-dead-letter-exchange", DIRECTEXCHANGE);
    arguments.put("x-dead-letter-routing-key", DIRECTIONKEY);
    return new Queue(QUEUEDEAD, true, false, false,arguments);
}

@Bean
public Binding deadBinding(){
    return BindingBuilder.bind(deadLetterQueue()).to(directExchange()).with(QUEUEDEAD);
}
public void deadSend() {
    MessagePostProcessor processor = new MessagePostProcessor() {
        @Override
        public Message postProcessMessage(Message message) throws AmqpException {
            message.getMessageProperties().setExpiration("60000");
            return message;
        }
    };
    log.info("延時訊息開始傳送:");
    rabbitTemplate.convertAndSend(RabbitConfig.DIRECTEXCHANGE, RabbitConfig.QUEUEDEAD, msg,processor);
}

通過上述程式碼我們就能實現傳送一個訊息,會出現延時的效果。這就是我們平時30分鐘支付的效果程式碼。

總結

這篇文章比較長,讀者還是需要耐心的閱讀的。乾貨多多。

加入戰隊

# 加入戰隊

微信公眾號

相關推薦

結合生活案例實現rabbitmq訊息通訊

ps : 這篇文章比較長,讀者還是需要耐心的閱讀的。乾貨多多。 在分散式專案中為了提高效能,也為了實現專案規範,我們都會在處理訊息佇列的時候引入訊息中介軟體。中介軟體的作用一個是為了解耦,還有一個是效能提升。訊息中介軟體我們每個人每天都在接觸,相信大家都用過美團或者是聽過美團。從程式設計師的角度看美團外賣涉及

RabbitMQ訊息通訊中介軟體中的那些概念

本章主要內容 瞭解rabbitmq的誕生 環境設定與安裝 AMQP協議 訊息通訊概念-----生產者與消費者 訊息持久化   瞭解rabbitmq的誕生         20世紀80年代,IBM、微軟

RabbitMQ訊息通訊,生產者傳送訊息給指定的消費者的訊息佇列

上一篇文章描述了,通過使用廣播式的通訊方式,讓生產者把訊息廣播給每一個消費者,本節我們介紹另外一個方式,生產者可以指定消費者,把訊息傳送給它: client.py #!/usr/bin/env python import pika import sys connectio

RabbitMQ訊息通訊,一個生產者和多個消費者,廣播式訊息通訊

上一則我們說到了一個對多個的RabbitMQ訊息佇列通訊的實現方法,生產者傳送的訊息只能被一個消費者接收並處理,上則請閱讀:http://blog.csdn.net/u012631731/article/details/78450389 本則說的是廣播式的訊息通訊方法實現,

RabbitMQ訊息通訊,一個生產者和多個消費者

上一則文章講解了RabbitMQ的安裝和簡單一對一訊息通訊實現方法,具體可參考上一篇文章:http://blog.csdn.net/u012631731/article/details/72887588 這則文章講述一個生產者和多個消費者的訊息通訊。 直接上原始碼,在原始

java實現rabbitmq訊息的傳送接受

本文不介紹amqp和rabbitmq相關知識,請自行網上查閱 本文是基於spring-rabbit中介軟體來實現訊息的傳送接受功能 see http://www.rabbitmq.com/tutorials/tutorial-one-java.html see http:/

java代碼實現highchart與數據庫數據結合完整案例分析(一)---餅狀圖

隱藏 des log cred 數據庫數據 idt string 時間 input 作者原創:轉載請註明出處 在做項目的過程中,經常會用到統計數據,同時會用到highchart或echart進行數據展示,highchart是外國開發的數據統計圖插件, echa

java代碼實現highchart與數據庫數據結合完整案例分析(二)---折線圖

end idt 。。 客戶端 屬性 hid pla 循環 scrip 作者原創:未經博主允許不許轉載 在上一篇的博客中,展示和分析了如何做一個餅狀圖,有疑問可以參考上一篇博客。 現在分析和展示折線圖的繪制和案例分析, 先展示效果圖: 與餅狀圖不同的是,折線圖展現更多的數據

Storm框架:如何消費RabbitMq訊息(程式碼案例)

1、定義拓撲topology public class MessageTopology { public static void main(String[] args) throws Exception { //組裝topology TopologyBuilder

rabbitmq實現延遲訊息(附原始碼)

rabbitmq實現延遲訊息的方案 1. 使用延時佇列 單機不考慮拓展的情況下,可以使用java.util.concurrent包的DelayQueue, 但插入的物件需實現Delayed介面,並實現其getDelay方法。 優點:針對任意訊息佇列均可使用 缺

基於Java NIO2實現的非同步非阻塞訊息通訊框架

原文傳送門 基於Java NIO2實現的非同步非阻塞訊息通訊框架 前奏 AIO應用開發 Future方式 Callback方式 Reader/Writer方式實現 執行緒池和Group PendingExceptio

rabbitMQ實現可靠訊息投遞

    RabbitMQ訊息的可靠性主要包括兩方面,一方面是通過實現消費的重試機制(通過@Retryable來實現重試,可以設定重試次數和重試頻率,但是要保證冪等性),另一方面就是實現訊息生產者的可靠投遞(注意消費單冪等),下面主要講下生產者實現的可靠訊息投遞。  

RabbitMQ系列之七 分散式訊息佇列應用場景之非同步處理、應用解耦、流量削鋒和訊息通訊理解分析

摘要:訊息佇列中介軟體是分散式系統中重要的元件,主要解決應用耦合,非同步訊息,流量削鋒等問題。實現高效能,高可用,可伸縮和最終一致性架構。是大型分散式系統不可缺少的中介軟體。 目前在生產環境,使用較多的訊息佇列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,

(十四)RabbitMQ訊息佇列-啟用SSL安全通訊

如果RabbitMQ服務在內網中,只有內網的應用連線,我們認為這些連線都是安全的,但是個別情況我們需要讓RabbitMQ對外提供服務。這種情況有兩種解決方案: 在RabbitMQ外層在封裝一層應用,應用對外提供服務,本質來說RabbitMQ還是隻對內網提供服務。相對更安全,但靈活

(十一)RabbitMQ訊息佇列-如何實現高可用

在前面講到了RabbitMQ高可用叢集的搭建,但是我們知道只是叢集的高可用並不能保證應用在使用訊息佇列時完全沒有問題,例如如果應用連線的RabbitMQ叢集突然宕機了,雖然這個叢集時可以使用的,但是應用訂閱的連線就斷開了,如果有個機房外網出口頻寬被挖掘機弄斷了,那叢集依然是不可用的。所以我們

Netty實戰開發(7):Netty結合kafka實現分散式訊息佇列

在分散式遊戲伺服器系統中,訊息處理佇列主要解決問題就是解耦系統中的業務,使得每個系統看起來功能比較單一,而且解決一些全服資料共享等問題。 通常我們知道kafka是作為訊息佇列比較火的一種方式,其實還有(Active MQ,Rabbit MQ,Zero MQ)個人

五、RabbitMQ-訊息可靠性傳遞實現方案

一、實現方案圖解 第一步 將要傳送的資訊進行對應資料庫的錄入,並且將傳送資訊的操作作為一條操作日誌錄入資料庫中設定狀態欄位status為0(傳送中)。 第二步 生產端將訊息傳送到RabbitMQ服務上。 第三步 RabbitMQ接收到訊息後,進行迴

RabbitMQ訊息可靠性投遞解決方案 - 基於SpringBoot實現

https://www.imooc.com/article/49814 參考地址: https://www.imooc.com/t/2726237 談到訊息的可靠性投遞,無法避免的,在實際的工作中會經常碰到,比如一些核心業務需要保障訊息不丟失,接下來我們看一個可靠性投遞的流程圖,說明可靠

入門RabbitMQ訊息佇列結合SSH框架(配置篇)

使用RabbitMQ訊息佇列,因為訊息佇列的非同步思想,解耦,以及允許短暫的不一致性,就像我現在把東西放在桌子上,你可以去拿,別人也可以去拿,而我不用等人拿完我便放東西上去,這樣就保證了我(生產者)和接收者沒有什麼聯絡,而且接受者可以隨時去拿。我們要使用RabbitMQ,安裝

redis 系列(十)java結合redis+lua 實現搶紅包經典案例

使用lua指令碼來實現一個搶紅包的過程,lua具有原子特性,可以避免資料併發時多執行緒同時操作的問題 java程式碼結合lua實現搶紅包案例 單機版redis package bhz.redis01; import java.util.Random; import java