docker部署rabbitMQ
由于常规的rabbitMQ部署需要配置很多依赖,而且容易因为版本的问题而导致部署失败,所以这里采用docker部署方式,不熟悉docker部署的可以看下面这篇文章:
拉取镜像
docker pull rabbitmq:management
如果出现因网络而拉取失败的可以参考以下文章:
2024 最新docker仓库镜像,6月,7月_最新docker镜像源-CSDN博客
启动容器
docker run -e RABBITMQ_DEFAULT_USER=root
-e RABBITMQ_DEFAULT_PASS=1234
-v mq-plugins:/plugins
--name mq3
-p 15672:15672
-p 5672:5672
-d rabbitmq:management
如果出现启动容器后容器立即关闭可以参考以下文章:
docker启动容器之后马上又自动关闭了_docker 容器 启动又秒退-CSDN博客
如果还不行,就检查容器日志:
docker logs 容器名
如果出现下面的报错:
Failed to create thread: Operation not permitted (1)
可以在启动容器的命令中加入以下命令:
--privileged=true
启动成功后查看运行的容器:
docker ps
成功后显示:
访问http://localhost:15672/显示:
rabbitMQ数据隔离
一个rabbitMQ服务下可能有多个消费者和生产者,不同的服务之间需要进行数据隔离,我们可以通过在rabbitMQ主机中创建虚拟主机来实现数据隔离
创建一个用户:
使用创建的用户再次登录后为该用户创建一个虚拟主机:
这样一来,不同的用户访问各自的虚拟主机,服务之间的数据也就隔离开来了。
Spring AMQP
Spring AMQP (Asynchronous Message Passing Protocol) 是 Spring Framework 的一个扩展模块,用于简化基于 AMQP (Advanced Message Queuing Protocol) 的消息中间件(如 RabbitMQ)的集成。
pom.xml引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
yml配置
消费者端
spring:
application:
name: consumer
rabbitmq:
host: localhost
port: 5672
virtual-host: /demo #主机下的虚拟机名
username: root2
password: 1234
生产者端
spring:
application:
name: producer
rabbitmq:
host: localhost
port: 5672
virtual-host: /demo #主机下的虚拟机名
username: root2
password: 1234
消息推送和接收
在rabbitMQweb端创建一个队列:
消息推送:
测试样例:
@SpringBootTest
class Demo1ApplicationTests {
@Resource
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
String QueueName="demo.queue";
String msg="hello rabbitmq";
rabbitTemplate.convertAndSend(QueueName,msg);
}
}
消息接收:
创建一个监听器类:
样例如下:
@Component
public class RabbbitmqDemo {
@RabbitListener(queues = "demo.queue")
public void receiveMsg(String msg){
System.out.println(msg);
}
}
先运行生产者后运行消费者,运行结果如下:
work模型
work模型简而言之就是多个消费者绑定一个队列,从而提高消息处理的速度,
同时要记得在yml文件中配置以下信息,否则就会出现一个快的消费者和一个慢的消费者同时拉取到相同数量的消息,正常的情况应该是快的处理的消息要多,这样才能充分利用起多个消费者协同合作的性能:
spring:
application:
name: consumer
rabbitmq:
host: localhost
port: 5672
virtual-host: /demo #主机下的虚拟机名
username: root2
password: 1234
listener:
simple:
prefetch: 1 #每次只能获取一条消息,处理完才能获取下一条消息
交换机
以上消息推送和接收均是访问队列,而在实际的开发中是先访问交换机后,由交换机来转发消息给队列,常见的交换机有以下几种:
fanout
一个交换机分发给多个队列:
direct
也就是每个队列都会与一个key相关联,比如我有一个支付业务,那么这个业务就可以将消息发送给所有与"pay"(实际的key要在向交换机中添加队列时自定义)绑定的队列
topic
topic与direct最大的不同就是它可以根据通配符绑定比如在发送消息时绑定key=“pay.#”,那么消息就会发送给所有和类似于("pay.red","pay.yellow","pay.blue")的关键词绑定的队列
在java中定义交换机和队列
在rabbitmq网页端定义交换机和队列,不免有些麻烦,下面提供了一种在java代码中定义交换机和队列的方式:
这里只需要在消费者监听器上添加以下的注解,如果是fanout交换机,那么就可以省略key的定义(此注解为样例实际需要自己根据模板定义):
@RabbitListener(bindings = @QueueBinding(
value=@Queue(name="队列名",durable = "true"可持久化设置,true代表开启),
exchange = @Exchange(name="交换机名",type = ExchangeTypes.DIRECT 交换机类型),
key={"red","yellow"}和队列绑定的key
))
然后在生产者端定义交换机名和key就可以发送到特定的队列中,如果是fanout交换机,那么就可以省略key的定义
@SpringBootTest
class Demo1ApplicationTests {
@Resource
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
String ExchangeName="交换机名";
String msg="hello rabbitmq";
rabbitTemplate.convertAndSend(ExchangeName,"key的名称",msg);
}
}
消息转换器
除了字符串类型的对象,可能在实际开发中还需要其他的对象消息比如User,Map等,这个时候要想在消息队列中存储这些对象的json格式就需要用到消息转换器来实现转换,配置消息转换器的步骤如下: