RabbitMQ学习
RabbitMQ学习
1:docker安装RabbitMQ
1):拉取镜像
docker pull rabbitmq:3.7.7-management
2)创建容器
docker run -d --hostname my-rabbit --name rabbit -v /data/rabbitmq:/var/lib/rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:3-management
-d 后台运行容器;
--name 指定容器名;
-p 指定服务运行的端口(5672:应用访问端口;15672:控制台Web端口号);
-v 映射目录或文件;
--hostname 主机名(RabbitMQ的一个重要注意事项是它根据所谓的 “节点名称” 存储数据,默认为主机名);
-e 指定环境变量;(RABBITMQ_DEFAULT_VHOST:默认虚拟机名;RABBITMQ_DEFAULT_USER:默认的用户名;RABBITMQ_DEFAULT_PASS:默认用户名的密码)
3)进入管理页面
创建完容器之后,就可以访问管理界面了,管理界面URL
http://ip:15672/
用户名密码admin/admin
TIP:端口、用户名密码都是在第2)不创建容器的命令中设置的
2:Spring boot使用RabbitMQ
1):pom.xml中加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
此处不需要加版本号,因为spring boot 的依赖中已经声明了版本号了。
2)配置application.properties
#配置rabbitMQ
spring.rabbitmq.host=81.71.2.11
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
3) 直连交换机的Demo
3.1 配置 交换机 - 路由 - 队列
这里的配置,就是会在MQ中创建交换机-路由和队列,可以在管理页面中看到,其实如果原来有此队列了,我们只要负责发送和接收就可以了,这个配置类都可以不用了
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 直连交换机的配置
*/
@Configuration
public class DirectRabbitConfig {
//队列 起名 TestDirectQueue
@Bean
public Queue TestDirectQueue(){
// durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
// exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
// autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
// return new Queue("TestDirectQueue",true,true,false);
//一般设置一下队列的持久化就好,其余两个就是默认false
return new Queue("TestDirectQueue",true);
}
//队列2 TestDirectQueue2
@Bean
public Queue TestDirectQueue2(){
return new Queue("TestDirectQueue2",true);
}
//Direct交换机
@Bean
DirectExchange TestDirectExchange(){
return new DirectExchange("TestDirectExchange",true,false);
}
绑定 交换机 - 路由1 - 队列1
// 将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
@Bean
Binding bindingDirect(){
return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
}
//绑定
// 交换机 - 路由2 - 队列2
@Bean
Binding bindingDirect2(){
return BindingBuilder.bind(TestDirectQueue2()).to(TestDirectExchange()).with("TestDirectRouting2");
}
@Bean
DirectExchange lonelyDirectExchange() {
return new DirectExchange("lonelyDirectExchange");
}
}
3.2:直连交换机 发送消息
@Autowired
RabbitTemplate rabbitTemplate;
//发送的交换机名/路由 以及 数据rabbitTemplate.convertAndSend("TestDirectExchange","TestDirectRouting",dataMap);
3.3 直连交换机的接收
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
@RabbitListener(queues = "TestDirectQueue")
@Slf4j
public class DirectReceiver {
@RabbitHandler
public void process(Map testMessage){
log.info("Receiver 11111111111 " + testMessage.toString());
}
}
3.4总结
RabbitMQ的使用非常简单,如果已经有交换机-路由-队列的规则,那么就只要写发送和接收的就可以了。发送和接收可以说就很简单的一行代码可以搞定。
各交换机的特点
除了有直连交换机,还有扇形和主题交换机。
直连交换机特点
MSG -> EX -> route1 -> queue1 -> receiver
-> route2 -> queue2 - > receiver21
- > receiver22
消息发送到交换机,交换机 根据 路由 与 队列绑定 ,接收者 监听队列情况,一个队列多个接收者,会轮询发送。
扇形交换机特点
MSG - EX - queue1 -> receiver1
- queue2 -> receiver2
消息发送到交换机,交换机直接与 队列绑定(不通过路由,即使设置了路由,也会忽略)
一个交换机与多个队列绑定,会把消息推送到多个队列里面,多个接收者 同时接收到这消息
主题交换机
* (星号) 用来表示一个单词 (必须出现的)
# (井号) 用来表示任意数量(零个或多个)单词
队列Q1 绑定键为 *.TT.* 队列Q2绑定键为 TT.#
如果一条消息携带的路由键为 A.TT.B,那么队列Q1将会收到;
如果一条消息携带的路由键为TT.AA.BB,那么队列Q2将会收到;
当一个队列绑定键为 “#”时,会接收所有的交换机的消息,相当于扇形交换机
当 * (星号) 和 # (井号) 这两个特殊字符都未在绑定键中出现的时候,此时主题交换机就拥有的直连交换机的行为
其它交换机的发送和接收
交换机的接收没有任何区别,发送的话,也基本一致,其它交换机的发送:
扇形交换机
rabbitTemplate.convertAndSend("FanoutExchange",null,dataMap);
主题交换机
rabbitTemplate.convertAndSend("topicExchange","topic.second",dataMap);
扇形交换机的配置
/**
* 扇形 交换机
*/
@Configuration
public class FanoutRabbitConfig {
//配置队列
@Bean
public Queue FanoutQueue1(){
return new Queue("FanoutQueue1",true);
}
@Bean
public Queue FanoutQueue2(){
return new Queue("FanoutQueue2",true);
}
//配置交换机
@Bean
public FanoutExchange FanoutExchange(){
return new FanoutExchange("FanoutExchange");
}
//配置交换机 - 队列绑定
@Bean
public Binding bindingFanoutExchange(){
return BindingBuilder.bind(FanoutQueue1()).to(FanoutExchange());
}
@Bean
public Binding bindingFanoutExchange2(){
return BindingBuilder.bind(FanoutQueue2()).to(FanoutExchange());
}
}
主题交换机的配置:
//主题交换机配置
@Configuration
public class TopicRabbitConfig {
@Bean
public Queue firstQueue(){
return new Queue("topicFirstQueue");
}
@Bean
public Queue secondQueue(){
return new Queue("topicSecondQueue");
}
@Bean
public TopicExchange exchange(){
return new TopicExchange("topicExchange");
}
@Bean
public Binding bindingExchangeMessage(){
return BindingBuilder.bind(firstQueue()).to(exchange()).with("topic.first");
}
@Bean
public Binding bindingExchangeMessage2(){
return BindingBuilder.bind(secondQueue()).to(exchange()).with("topic.#");
}
}