添加一个账号****
在RabbitMQ添加一个新的用户
RabbitMQ服务器上
创建账号
rabbitmqctl add_user admin “密码”
设置用户角色
rabbitmqctl set_user_tags admin administrator
1、超级管理员(administrator)
可登陆管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
2、监控者(monitoring)
可登陆管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)
3、策略制定者(policymaker)
可登陆管理控制台, 同时可以对policy进行管理。但无法查看节点的相关信息(上图红框标识的部分)。
4、普通管理者(management)
仅可登陆管理控制台,无法看到节点信息,也无法对策略进行管理。
5、其他
无法登陆管理控制台,通常就是普通的生产者和消费者。
设置用户权限
rabbitmqctl ?set_permissions ?-p ?'/' ?user_name '.' '.' '.'
查询当前用户信息
rabbitmqctl list_users
设置成功后可用用户登录rabbitMQ页面
Spring-boot对RabbitMQ的引用****
RabbitMq依赖为
org.springframework.boot
spring-boot-starter-amqp
在配置文件中添加RabbitMq相关配置信息
# rabbitmq:**
# host: ${rabbitmq.ip}**
# port: ${port}**
# username: ${rabbitmqUser}**
# password: ${rabbitmqPassword}**
# listener:**
# # 默认配置是 simple**
# type: simple**
# simple:**
# # ack Acknowledge mode of container. auto none**
# #acknowledge-mode: manual**
# # Maximum number of unacknowledged messages that can be outstanding at each consumer.**
# #prefetch: 3
配置详解****
spring.rabbitmq.host: 服务Host
spring.rabbitmq.port: 服务端口
spring.rabbitmq.username: 登陆用户名
spring.rabbitmq.password: 登陆密码
spring.rabbitmq.virtual-host: 连接到rabbitMQ的vhost
spring.rabbitmq.addresses: 指定client连接到的server的地址,多个以逗号分隔(优先取addresses,然后再取host)
spring.rabbitmq.requested-heartbeat: 指定心跳超时,单位秒,0为不指定;默认60s
spring.rabbitmq.publisher-confirms: 是否启用【发布确认】
spring.rabbitmq.publisher-returns: 是否启用【发布返回】
spring.rabbitmq.connection-timeout: 连接超时,单位毫秒,0表示无穷大,不超时
spring.rabbitmq.parsed-addresses:
ssl
spring.rabbitmq.ssl.enabled: 是否支持ssl
spring.rabbitmq.ssl.key-store: 指定持有SSL certificate的key store的路径
spring.rabbitmq.ssl.key-store-password: 指定访问key store的密码
spring.rabbitmq.ssl.trust-store: 指定持有SSL certificates的Trust store
spring.rabbitmq.ssl.trust-store-password: 指定访问trust store的密码
spring.rabbitmq.ssl.algorithm: ssl使用的算法,例如,TLSv1.1
cache
spring.rabbitmq.cache.channel.size: 缓存中保持的channel数量
spring.rabbitmq.cache.channel.checkout-timeout: 当缓存数量被设置时,从缓存中获取一个channel的超时时间,单位毫秒;如果为0,则总是创建一个新channel
spring.rabbitmq.cache.connection.size: 缓存的连接数,只有是CONNECTION模式时生效
spring.rabbitmq.cache.connection.mode: 连接工厂缓存模式:CHANNEL 和 CONNECTION
listener
spring.rabbitmq.listener.simple.auto-startup: 是否启动时自动启动容器
spring.rabbitmq.listener.simple.acknowledge-mode: 表示消息确认方式,其有三种配置方式,分别是none、manual和auto;默认auto
spring.rabbitmq.listener.simple.concurrency: 最小的消费者数量
spring.rabbitmq.listener.simple.max-concurrency: 最大的消费者数量
spring.rabbitmq.listener.simple.prefetch: 指定一个请求能处理多少个消息,如果有事务的话,必须大于等于transaction数量.
spring.rabbitmq.listener.simple.transaction-size: 指定一个事务处理的消息数量,最好是小于等于prefetch的数量.
spring.rabbitmq.listener.simple.default-requeue-rejected: 决定被拒绝的消息是否重新入队;默认是true(与参数acknowledge-mode有关系)
spring.rabbitmq.listener.simple.idle-event-interval: 多少长时间发布空闲容器时间,单位毫秒
spring.rabbitmq.listener.simple.retry.enabled: 监听重试是否可用
spring.rabbitmq.listener.simple.retry.max-attempts: 最大重试次数
spring.rabbitmq.listener.simple.retry.initial-interval: 第一次和第二次尝试发布或传递消息之间的间隔
spring.rabbitmq.listener.simple.retry.multiplier: 应用于上一重试间隔的乘数
spring.rabbitmq.listener.simple.retry.max-interval: 最大重试时间间隔
spring.rabbitmq.listener.simple.retry.stateless: 重试是有状态or无状态
template
spring.rabbitmq.template.mandatory: 启用强制信息;默认false
spring.rabbitmq.template.receive-timeout: receive() 操作的超时时间
spring.rabbitmq.template.reply-timeout: sendAndReceive() 操作的超时时间
spring.rabbitmq.template.retry.enabled: 发送重试是否可用
spring.rabbitmq.template.retry.max-attempts: 最大重试次数
spring.rabbitmq.template.retry.initial-interval: 第一次和第二次尝试发布或传递消息之间的间隔
spring.rabbitmq.template.retry.multiplier: 应用于上一重试间隔的乘数
spring.rabbitmq.template.retry.max-interval: 最大重试时间间隔
消息队列的使用****
1.简单队列****
P:生产者
P和C之间:队列
C:消费者
管理工具中创建队列:
message TTL:消息生存时间,超过设置时间自动删除
auto expire:队列生存时间,超过设置时间自动删除
overflow behaviour:队列溢出行为,可设置drop-head, reject-publish 或reject-publish-dlx,
drop-head会丢弃最老的消息,reject-publish或reject-publish-dlx会丢弃最新的消息
dead letter exchange:死信交换机,如果消息被拒绝或过期,将发布到改交换机绑定的队列
dead letter routing key:死信交换机路由,由该交换机根据路由键发给队列
max length:最大消息容量,超过会从头部丢弃
max length bytes:最大消息容量字节数,超过会从头部丢弃
maximum priority:最大优先级,消息的优先级参数越靠近最大优先级,越早被消费
lazy mode:惰性模式,在磁盘上保留尽可能多的消息,以减少RAM的使用,否则是一个内存缓存,尽可能快的传递消息
创建一个队列如图中所示:
后创建生产者
此处为传输一个序列化UserLogForm对象
创建一个消费者
触发该生产者方法数据会传输到RabbitMQ中发给消费者消费
2 . 工作队列****
代码跟上一个队列基本一样,不过工作队列有两个消费者:
工作队列是以公平方式,轮询发送消息到消费者。
5.3 发布/订阅队列(publish/subscribe)****
发布、订阅队列是以fanout 广播方式发送消息给消费者的
queue、exchange配置
package com.example.demo.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueAndExchangeConfig {
//第一个队列:my-first-queue
@Bean("myFirstQueue")
public Queue getFirstQueue(){
return new Queue("my-first-queue");
}
//第二个队列:my-second-queue
@Bean("mySecondQueue")
public Queue getSecondQueue(){
return new Queue("my-second-queue");
}
//第一个交换机:my-first-exchange
@Bean("myFirstExchange")
FanoutExchange getMyFirstExchange(){
return new FanoutExchange("my-first-exchange");
}
//将my-first-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingFirstQueueToFanoutExchange(){
return BindingBuilder.bind(getFirstQueue()).to(getMyFirstExchange());
}
//将my-second-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingSecondQueueToFanoutExchange(){
return BindingBuilder.bind(getSecondQueue()).to(getMyFirstExchange());
}
}
生产者:
package com.example.demo.controller;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("producer")
public class ProducerController{
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/producerSendFirstExchange")
public String sendMsg(@RequestParam(value = "msg") String msg){
rabbitTemplate.convertAndSend("my-first-exchange","",msg);
return msg;
}
}
消费者:
package com.example.demo.config;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class ConsumerHandler {
@RabbitListener(queues = "my-first-queue")
public void getFirstQueue(String msg){
System.out.println("消费者1:"+msg);
}
@RabbitListener(queues = "my-second-queue")
public void getSecondQueue(String msg){
System.out.println("消费者2:"+msg);
}
}
跟工作队列(work queue)做个比较,有什么不同和相同点:
不同:发布/订阅队列需要创建一个交换机并将队列绑定到交换机,而工作队列不需要
相同:多个消费者监听同一个队列,消息不会被重复消费
4 路由队列(routing)****
路由队列是以direct routing = key方式发送消息给消费者的
queue 可以通过一个或多个routing key绑定到Exchange上,不同queue相同routing ke绑定到Exchange也是完全可以的
queue、exchange配置:
package com.example.demo.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueAndExchangeConfig {
//第一个队列:my-first-queue
@Bean("myFirstQueue")
public Queue getFirstQueue(){
return new Queue("my-first-queue");
}
//第二个队列:my-second-queue
@Bean("mySecondQueue")
public Queue getSecondQueue(){
return new Queue("my-second-queue");
}
//第一个交换机:my-first-exchange
@Bean("myFirstExchange")
DirectExchange getMyFirstExchange(){
return new DirectExchange("my-first-exchange");
}
//将以my-first-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingFirstQueueToFanoutExchange(){
return BindingBuilder.bind(getFirstQueue()).to(getMyFirstExchange()).with("orange");
}
//将以my-second-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingSecondQueueToFanoutExchange(){
return BindingBuilder.bind(getSecondQueue()).to(getMyFirstExchange()).with("green");
}
}
生产者:
package com.example.demo.controller;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("producer")
public class ProducerController{
@Autowired
private RabbitTemplate rabbitTemplate;
@GetMapping("/producerSendFirstQueue")
public String sendMsg(@RequestParam(value = "msg") String msg){
rabbitTemplate.convertAndSend("my-first-exchange","green",msg);
return msg;
}
}
消费者:
package com.example.demo.config;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class ConsumerHandler {
@RabbitListener(queues = "my-first-queue")
public void getFirstQueue(String msg){
System.out.println("消费者1:"+msg);
}
@RabbitListener(queues = "my-second-queue")
public void getSecondQueue(String msg){
System.out.println("消费者2:"+msg);
}
}
如果将my-first-queue与my-second-queue的routing-key(路由键)都设置成一样的值,那消费者1和消费者2都会收到消息,一个queue如果有多个routing-key,任意一个routing-key都可以路由到queue中,然后被消费
5 通配符队列(Topics)****
通配符队列这种模式是基于routing 模式上优化的一种队列,需要了解两种通配符规则:
*:匹配任意一个单词
#:匹配任意一个或多个单词
例子:
rabbit.*:匹配rabbit.first
rabbit.#:匹配rabbit.first 或者 rabbit.first.two
如果没有匹配的路由到队列,那么该消息会丢失
queue、exchange配置:
package com.example.demo.config;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueAndExchangeConfig {
//第一个队列:my-first-queue
@Bean("myFirstQueue")
public Queue getFirstQueue(){
return new Queue("my-first-queue");
}
//第二个队列:my-second-queue
@Bean("mySecondQueue")
public Queue getSecondQueue(){
return new Queue("my-second-queue");
}
//第一个交换机:my-first-exchange
@Bean("myFirstExchange")
TopicExchange getMyFirstExchange(){
return new TopicExchange("my-first-exchange");
}
//将以my-first-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingFirstQueueToFanoutExchange(){
return BindingBuilder.bind(getFirstQueue()).to(getMyFirstExchange()).with("green.*");
}
//将以my-second-queue队列绑定到my-first-exchange交换机上
@Bean
Binding bindingSecondQueueToFanoutExchange(){
return BindingBuilder.bind(getSecondQueue()).to(getMyFirstExchange()).with("green.#");
}
}
生产者:
@GetMapping("/producerSendFirstQueue")
public String sendMsg(@RequestParam(value = "msg") String msg){
rabbitTemplate.convertAndSend("my-first-exchange","green.red",msg);
return msg;
}
消费者还是监听my-first-queue和my-second-queue两个队列
两个消费都匹配,并且路由到queue上被消费了
@GetMapping("/producerSendFirstQueue")
public String sendMsg(@RequestParam(value = "msg") String msg){
rabbitTemplate.convertAndSend("my-first-exchange","green.red.blue",msg);
return msg;
}
结果是my-second-queue收到消息然后消费了