使用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/
若是您想及時獲得我的撰寫文章以及著做的消息推送,能夠掃描上方二維碼,關注我的公衆號哦。