一:消息队列
1.举例分析:
小红希望小明多读书 , 常寻找好书给小明看 , 之前的方式是这样:小红问小明什么时候有空 , 把书给小明送去 , 并亲眼监督小明读完书才走 . 久而久之 , 两人都觉得麻烦 .后来的方式改成了:小红对小明说「我放到书架上的书你都要看」 , 然后小红每次发现不错的书都放到书架上 , 小明则看到书架上有书就拿下来看 .书架就是一个消息队列 , 小红是生产者 , 小明是消费者 .带来的好处1. 小红想给小明书的时候 , 不必问小明什么时候有空 , 亲手把书交给他了 , 小红只把书放到书架上就行了 . 这样小红小明的时间都更自由 .2. 小红相信小明的读书自觉和读书能力 , 不必亲眼观察小明的读书过程 , 小红只要做一个放书的动作 , 很节省时间 .3. 当明天有另一个爱读书的小伙伴小强加入 , 小红仍旧只需要把书放到书架上 , 小明和小强从书架上取书即可4. 书架上的书放在那里 , 小明阅读速度快就早点看完 , 阅读速度慢就晚点看完 , 没关系 , 比起小红把书递给小明并监督小明读完的方式 , 小明的压力会小一些 .消息队列特点1. 解耦 : 每个成员不必受其他成员影响 , 可以更独立自主 , 只通过一个简单的容器来联系 .2. 提速 : 小红选只要做一个放书的动作 , 为自己节省了大量时间 .3. 广播 : 小红只需要劳动一次 , 就可以让多个小伙伴有书可读 , 这大大地节省了她的时间 , 也让新的小伙伴的加入成本很低 .4. 错峰与流控 : 小红给书的频率不稳定 , 如果今明两天连给了五本 , 之后隔三个月才又给一本 , 那小明只要在三个月内从书架上陆续取走五本书读完就行了 , 压力就不那么大了 .
2.AMQP
含义:一个提供统一消息服务的应用层标准高级消息队列协议,是一个通用的应用层协议
二:RabbitMQ
1.含义: RabbitMQ是一个实现了AMQP(Advanced Message Queuing Protocol)高级消息队列协议的消息队列服务,用Erlang语言.
Server(Broker): 接收客户端连接 , 实现 AMQP 协议的消息队列和路由功能的进程 .Virtual Host :虚拟主机的概念 , 类似权限控制组 , 一个 Virtual Host 里可以有多个 Exchange 和 Queue.Exchange: 交换机 , 接收生产者发送的消息 , 并根据 Routing Key 将消息路由到服务器中的队列 Queue.ExchangeType: 交换机类型决定了路由消息行为 ,RabbitMQ 中有三种类型 Exchange, 分别是 fanout 、 direct 、 topic.Message Queue :消息队列 , 用于存储还未被消费者消费的消息 .Message :由 Header 和 body 组成 ,Header 是由生产者添加的各种属性的集合 , 包括 Message 是否被持久化、优先级是多少、由哪个 Message Queue 接收等 .body 是真正需要发送的数据内容 .BindingKey :绑定关键字 , 将一个特定的 Exchange 和一个特定的 Queue 绑定起来 .
三:Docker安装部署RabbitMQ
1.拉取rabbitMQ
docker pull rabbitmq:management
2.新建rabbitMQ
docker run -d \ --name my-rabbitmq \ -p 5672:5672 -p 15672:15672 \ -v /home/rabbitmq:/var/lib/rabbitmq \ --hostname my-rabbitmq-host \ -e RABBITMQ_DEFAULT_VHOST=my_vhost \ -e RABBITMQ_DEFAULT_USER=admin \ -e RABBITMQ_DEFAULT_PASS=admin \ --restart=always \ rabbitmq:management
3.进入管理页面
http://主机地址+配置的rabbitMQ端口号
四:springboot连接配置
1.创建一个项目
格式:rabbitMQ ------父项目用来存放子项目共有的pom依赖
- consumer ------接收者(用来接收生产者传的信息)
- provider ------生产者2.pom文件
父项目------rabbitMQ
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>rabbitMQ</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>provider</module> <module>consumer</module> </modules> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.4.1</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.3</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
生产者------provider
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>provider</artifactId> <version>0.0.1-SNAPSHOT</version> <name>provider</name> <description>Demo project for Spring Boot</description> <parent> <artifactId>rabbitMQ</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.provider.ProviderApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
消费者------consumer
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>consumer</name> <description>Demo project for Spring Boot</description> <parent> <artifactId>rabbitMQ</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.4.1</version> <configuration> <mainClass>com.example.consumer.ConsumerApplication</mainClass> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
3.yml配置
server: port: 8082 spring: application: name: provider rabbitmq: host: 主机端口号 password: 密码 port: 配置的访问端口 username: springboot virtual-host: my_vhost
4.生产者里面创建队列
package com.example.provider; import org.springframework.amqp.core.Queue; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @SuppressWarnings("all") public class RabbitConfig { @Bean public Queue firstQueue() { return new Queue("firstQueue"); } }
5.往队列里面传数据
package com.example.provider; import org.springframework.amqp.core.AmqpTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @SuppressWarnings("all") public class Sender { @Autowired private AmqpTemplate rabbitTemplate; public void sendFirst() { rabbitTemplate.convertAndSend("firstQueue", "Hello World"); } }
6.消费者接收数据
package com.example.consumer; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component @Slf4j @RabbitListener(queues = "firstQueue") public class Receiver { @RabbitHandler public void process(String msg) { log.warn("接收到:" + msg); } }
7.运行
注:先运行生产者再运行消费者
五:自定义数据发送
例:要发送一个User对象过去
如果用上面这种方法会报错因为生产者那边传一个User对象过去会把User所在哪个目录下也一起传送过去消费者必须在相同软件包目录下才能接收,所以我们采用先在生产者中转换成json格式的数据传给消费者,然后消费者拿到后再转回来就可以了
1.生产者和消费者新建一个User类
package com.example.provider; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @SuppressWarnings("all") @Data @AllArgsConstructor @NoArgsConstructor public class User { private String username; private String userpwd; }
2.再sender类中传一个json
public void send(User user) { rabbitTemplate.convertAndSend("first", user); } public void sendFirst(String json) { rabbitTemplate.convertAndSend("firstQueue", json); }
3.消费者接收数据
@RabbitHandler @SneakyThrows public void process(String json) { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.readValue(json,User.class); log.warn("接收:" + json); }
然后运行就可以了