RabbitMQ消息隊列基礎概念、原理學習

使用RabbitMQ實現解耦合的設計,對添加代碼是開發的,對修改代碼是關閉的。歐耶!!!java

一、什麼是生產者Provider?web

  答:消息生產者,就是投遞消息的程序。spring

二、什麼是消費者Consumer?apache

  答:消息消費者,就是接受消息的程序。瀏覽器

三、沒有使用消息隊列時消息傳遞方式。服務器

四、使用消息隊列後消息傳遞方式。 架構

五、什麼是隊列?app

  答:隊列就像存放了商品的倉庫或者商店,是生產商品的工廠和購買商品的用戶之間的中轉站。maven

六、隊列裏存儲了什麼?ide

  答:在RabbitMQ 中,信息流從你的應用程序出發,來到 Rabbitmq 的隊列,全部信息能夠只存儲在一個隊列中。隊列能夠存儲不少信息,由於它基本上是一個無限制的緩衝區,前提是你的機器有足夠的存儲空間。

七、隊列和應用程序的關係?

  答:多個生產者能夠將消息發送到同一個隊列中,多個消息者也能夠只從同一個隊列接收數據。

八、RabbitMQ的生產者消費者模型、使用SpringBoot搭建。因爲建立的SpringBoot項目,使用Maven。依賴包以下所示:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
 5     https://maven.apache.org/xsd/maven-4.0.0.xsd">
 6     <modelVersion>4.0.0</modelVersion>
 7     <parent>
 8         <groupId>org.springframework.boot</groupId>
 9         <artifactId>spring-boot-starter-parent</artifactId>
10         <version>2.1.1.RELEASE</version>
11         <relativePath /> <!-- lookup parent from repository -->
12     </parent>
13     <groupId>com.bie</groupId>
14     <artifactId>rabbitmq</artifactId>
15     <version>0.0.1-SNAPSHOT</version>
16     <name>rabbitmq</name>
17     <description>Demo project for Spring Boot</description>
18 
19     <properties>
20         <java.version>1.8</java.version>
21     </properties>
22 
23     <dependencies>
24         <dependency>
25             <groupId>org.springframework.boot</groupId>
26             <artifactId>spring-boot-starter</artifactId>
27         </dependency>
28         <dependency>
29             <groupId>org.springframework.boot</groupId>
30             <artifactId>spring-boot-starter-web</artifactId>
31         </dependency>
32         <dependency>
33             <groupId>org.springframework.boot</groupId>
34             <artifactId>spring-boot-starter-test</artifactId>
35             <scope>test</scope>
36         </dependency>
37         <dependency>
38             <groupId>org.springframework.boot</groupId>
39             <artifactId>spring-boot-starter-amqp</artifactId>
40         </dependency>
41     </dependencies>
42 
43     <build>
44         <plugins>
45             <plugin>
46                 <groupId>org.springframework.boot</groupId>
47                 <artifactId>spring-boot-maven-plugin</artifactId>
48             </plugin>
49         </plugins>
50     </build>
51 
52 </project>

配置你的SpringBoot的配置文件application.properties。

 1 # 給當前項目起名稱.
 2 spring.application.name=rabbitmq
 3 
 4 # 配置rabbitmq的參數.
 5 # rabbitmq服務器的ip地址.
 6 spring.rabbitmq.host=192.168.110.133
 7 # rabbitmq的端口號5672,區別於瀏覽器訪問界面的15672端口號.
 8 spring.rabbitmq.port=5672
 9 # rabbitmq的帳號.
10 spring.rabbitmq.username=guest
11 # rabbitmq的密碼.
12 spring.rabbitmq.password=guest
13 
14 # 隊列的名稱
15 rabbitmq.queue=queue001

而後,建立一個隊列,建立的隊列,在項目啓動的時候加載,這樣使用隊列的時候就能夠直接使用。

 1 package com.example.bie.config;
 2 
 3 import org.springframework.amqp.core.Queue;
 4 import org.springframework.beans.factory.annotation.Value;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 
 8 /**
 9  * 
10  * @author biehl
11  * 
12  * @Configuration項目啓動加載本類
13  * 
14  */
15 @Configuration
16 public class RabbitMqQueueConfig {
17 
18     @Value("${rabbitmq.queue}")
19     private String queueName;
20 
21     /**
22      * 建立一個隊列
23      * 
24      * @return
25      */
26     @Bean
27     public Queue createQueue() {
28         return new Queue(this.queueName);
29     }
30 
31 }

而後,建立一個Rabbitmq的生產者,生產消息,這裏使用傳入參數的方法生產消息。能夠測試單條消息和多條消息。

 1 package com.example.bie.rabbitmq.producer;
 2 
 3 import org.springframework.amqp.core.AmqpTemplate;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.beans.factory.annotation.Value;
 6 import org.springframework.stereotype.Component;
 7 
 8 /**
 9  * 
10  * @author biehl
11  *
12  *         RabbitmqProducer消息發送者
13  *
14  * @Component加入到容器中.
15  * 
16  */
17 @Component
18 public class RabbitmqProducer {
19 
20     @Autowired
21     private AmqpTemplate rabbitmqAmqpTemplate;
22 
23     @Value("${rabbitmq.queue}")
24     private String queueName;
25 
26     /**
27      * 發送消息的方法
28      */
29     public void producer(String msg) {
30         // 向消息隊列中發送消息
31         // 參數1,隊列的名稱
32         // 參數2,發送的消息
33         this.rabbitmqAmqpTemplate.convertAndSend(this.queueName, msg);
34     }
35 
36 }

建立消費者消費消息,因爲使用的是消費事件監聽器,這裏使用註解方式,一旦發現隊列裏面的消息發生變化,就觸發該事件,從而觸發方法進行消息的消費。

 1 package com.example.bie.rabbitmq.consumer;
 2 
 3 import org.springframework.amqp.rabbit.annotation.RabbitListener;
 4 import org.springframework.beans.factory.annotation.Value;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * 
 9  * @author biehl
10  *
11  *         RabbitmqConsumer消息消費者
12  * 
13  *         消費者是根據消息隊列的監聽器,進行消息的接收和消費。
14  * 
15  *         消息隊列發生變化,消息事件就會產生,觸發方法進行消息的接收。
16  * 
17  */
18 @Component
19 public class RabbitmqConsumer {
20 
21     @Value("${rabbitmq.queue}")
22     private String queueName;
23 
24     /**
25      * 消費者消費消息,接受消息的方法,採用消息隊列監聽機制.
26      * 
27      * @RabbitListener
28      * 
29      *                 意思是當隊列發生變化,消息事件產生了或者生產者發送消息了。
30      * 
31      *                 立刻就會觸發這個方法,進行消息的消費。
32      */
33     @RabbitListener(queues = "queue001")
34     public void consumer(String msg) {
35         // 打印消息
36         System.out.println("消費者===>消費<===消息message: " + msg);
37     }
38 
39 }

建立完畢隊列,生產者,消費者,配置好配置文件,可使用單元測試,或者使用Controller的方式進行測試。因爲使用單元測試,SpringBoot項目中止,就沒法進行消費,不方便測試,這裏使用web容器進行測試,建立一個Controller,頁面訪問進行觸發方法的執行。當生產者生產消息多的時候能夠在瀏覽器進行觀察生產、消費的效果。

 1 package com.example.bie.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Controller;
 5 import org.springframework.web.bind.annotation.RequestMapping;
 6 import org.springframework.web.bind.annotation.ResponseBody;
 7 
 8 import com.example.bie.rabbitmq.producer.RabbitmqProducer;
 9 
10 /**
11  * 
12  * @author biehl
13  *
14  */
15 @Controller
16 public class RabbitmqController {
17 
18     @Autowired
19     private RabbitmqProducer rabbitmqProducer;
20 
21     @RequestMapping(value = "/sendMessage")
22     @ResponseBody
23     public void rabbitmqSendMessage() {
24         String msg = "消息產===>生者<===消息message: ";
25         for (int i = 0; i < 100000; i++) {
26             rabbitmqProducer.producer(msg + i);
27         }
28     }
29 
30 }

最後就能夠啓動你的SpringBoot項目了。

 1 package com.example;
 2 
 3 import org.springframework.boot.SpringApplication;
 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
 5 
 6 @SpringBootApplication
 7 public class RabbitmqApplication {
 8 
 9     public static void main(String[] args) {
10         SpringApplication.run(RabbitmqApplication.class, args);
11     }
12 
13 }

運行效果以下所示:

九、RabbitMQ原理理解,概念的理解。

1)、RabbitMQ的消息Message。

  消息。消息是不具名的,它由消息頭、消息體組成。消息體是不透明的,而消息頭則由一系列可選屬性組成,這些屬性包括:routing-key(路由鍵)、priority(相對於其餘消息的優先權)、delivery-mode(指出消息可能持久性存儲)等。

2)、RabbitMQ的生產者Provider或者Publisher。

  消息的生產者。也是一個向交換器發佈消息的客戶端應用程序。

3)、RabbitMQ的消費者Consumer。

  消息的消費者。表示一個從消息隊列中取得消息的客戶端應用程序。

4)、RabbitMQ的交換器或者稱爲交換機Exchange。

  交換器。用來接收生產者發送的消息並將這些消息路由給服務器中的隊列。三種經常使用的交換器類型,包含,direct(發佈與訂閱 徹底匹配,默認使用)、fanout(廣播)、topic(主題,規則匹配)。

5)、RabbitMQ的綁定Binding。

  綁定。用於消息隊列Queue和交換器Exchange之間的關聯。一個綁定就是基於路由鍵將交換器和消息隊列鏈接起來的路由規則,因此能夠將交換器理解成一個由綁定構成的路由表。

6)、RabbitMQ的消息隊列Queue。

  消息隊列。用來保存消息直到發送給消費者。它是消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列裏面,等待消費者連接到這個隊列將其取走。

7)、RabbitMQ的路由鍵Routing-key。

  路由鍵。RabbitMQ 決定消息該投遞到哪一個隊列的規則。隊列經過路由鍵綁定到交換器。消息發送到 MQ 服務器時,消息將擁有一個路由鍵,即使是空的,RabbitMQ 也會將其和綁定使用的路由鍵進行匹配。若是相匹配,消息將會投遞到該隊列。若是不匹配,消息將會進入黑洞。

8)、RabbitMQ的連接Connection。

  連接。指Rabbitmq 服務器和服務創建的 TCP 連接。

9)、RabbitMQ的信道Channel。

  信道。a、Channel 中文叫作信道,是 TCP 裏面的虛擬連接。例如:電纜至關於 TCP,信道是一個獨立光纖束,一條 TCP 鏈接上建立多條信道是沒有問題的。b、TCP 一旦打開,就會建立 AMQP 信道。c、不管是發佈消息、接收消息、訂閱隊列,這些動做都是經過信道完成的。

10)、RabbitMQ的虛擬主機Virtual Host

  虛擬主機。表示一批交換器,消息隊列和相關對象。虛擬主機是共享相同的身份認證和加密環境的獨立服務器域。每一個 vhost 本質上就是一個 mini 版的 RabbitMQ 服務器,擁有本身的隊列、交換器、綁定和權限機制。vhost 是 AMQP 概念的基礎,必須在連接時指定, RabbitMQ 默認的 vhost 是/。

11)、RabbitMQ的消息隊列服務器實體Borker。

  表示消息隊列服務器實體。

12)、RabbitMQ交換器和隊列的關係。

  交換器是經過路由鍵和隊列綁定在一塊兒的,若是消息擁有的路由鍵跟隊列和交換器的路由鍵匹配,那麼消息就會被路由到該綁定的隊列中。
  也就是說,消息到隊列的過程當中,消息首先會通過交換器,接下來交換器在經過路由鍵匹配分發消息到具體的隊列中。
  路由鍵能夠理解爲匹配的規則。

13)、RabbitMQ 爲何須要信道?爲何不是 TCP 直接通訊?

  TCP 的建立和銷燬開銷特別大。建立須要 3 次握手,銷燬須要 4 次分手。
  若是不用信道,那應用程序就會以 TCP 連接 Rabbit,高峯時每秒成千上萬條連接會形成資源巨大的浪費,並且操做系統每秒處理 TCP 連接數也是有限制的,一定形成性能瓶頸。
  信道的原理是一條線程一條通道,多條線程多條通道同用一條 TCP 連接。一條 TCP 連接能夠容納無限的信道,即便每秒成千上萬的請求也不會成爲性能的瓶頸。

十、RabbitMQ的架構設計,以下圖所示

做者:別先生

博客園:https://www.cnblogs.com/biehongli/

若是您想及時獲得我的撰寫文章以及著做的消息推送,能夠掃描上方二維碼,關注我的公衆號哦。

相關文章
相關標籤/搜索