rabbitmq
快速大小写:ctrl+shift+u
linux:ctrl+alt+f2进入命令模式
rabbitmq安装文件在linux下的位置: /usr/local/software
1.基本命令: /sbin/service rabbitmq-server start :开启rabbtimq
/sbin/service rabbitmq-server stop :关闭rabbitmq
/sbin/service rabbitmq-server status:查看rabbitmq状态
rabbitmq-plugins enable rabbitmq_management :开启web管理插件, 从浏览器中输入ip地址:15672进入rabbitmqweb页面
rabbitmqctl add_user username password :创建一个rabbitmq的用户。
rabbitmqctl set_user_tags username administrator : 设定用户角色 ,adminisrator表示管理员
rabbitmqctl set_permissions -p "/" admin ".*" ".*" ".*" :设置用户权限,所有资源的写读。
rabbitmqctl list_users: 查看当前rabbitmq的用户
rabbitmqctl stop_app:关闭web页面
rabbitmqctl reset :清除命令
systemctl stop firewalld---关闭防火墙。
队列的声明:消费者和生产者都可以声明,两个都声明也可以。
2.轮训分发(公平分发): 在多个线程中获取同一个队列的消息是均分的过程。 eg:线程A,B。 队列C。 C中有1,2,3,4,四个消息, 那么线程A获得1,3.线程B获得2,4。
3.消息应答:防止消息的丢失。当消费者收到消息并且处理掉该消息后,告诉rabbitmq,然后rabbitmq将消息删除。
1.自动应答:消息发送后会被立即认为已经传递成功,如果消费者出现连接异常或者信道关闭,消息就会丢失。不建议。
2.手动应答:channel.basicAck()用于肯定确认收到消息,mq可以删除消息。 channel.basicNack()用于否定确认,没有收到消息。 比channel.basicReject()用于否定确认,拒绝接收消息。baiscNack少一个参数。 消费者宕机消息可以返回队列。
多个消费者在接收消息时,如果有一个消费者在接收消息时出现宕机,那么该消息会被重新发送给其他消费者。
4.队列持久化与消息持久化:都在生产者里设置,改参数。 在创建队列时,将对应的参数改为true--队列持久化。 在发布消息时,添加这个属性MessageProperties.PERSISTENT_TEXT_PLAIN ,--消息持久化
5.不公平分发:针对于消费者,能者多劳。 获得消息时间快的,分发消息更多。不像轮训分发的一人一个消息。 channel.basicQos(1) 直接设置1-表示不公平分发。
6.预取值:给消费者设置得到多少信息。 消息会按照消费者预取值在对应消费者的消费中排队,即使某个消费者处理速度慢,它的消息也不能被他人处理。eg:消费者a ,b 预取值分别时 2,3. 那么在队列中,a获得2,b获得3。
channel.basicQos(value) --表示预取value个数据。
7.发布确认(生产者):channel.confirmSelect()--开启发布确认。channel.waitForConfirms()--等待确认发布。 需要开启队列和消息持久化。
1.单个发布确认。发一条消息,确认一次。当第一条发布完成,在发送后变的消息。 如果发布失败,后边的消息也不能发送,
2.批量确认:
3.异步批量确认: 常用,性价比高,需要创建一个ConcurrentSkipListMap<Long, String> outstandingConfirms = new ConcurrentSkipListMap<>();
8.交换机:发布订阅模式。 因为消息在一个队列中只能被消费一次,交换机可以使消息被消费多次。生产者只能将消息发送给交换机。 “”空串表示默认的交换机。交换机绑定队列有一个routtingkey,消费者根据Routtingkey找到对应的队列。
9.临时队列:String queuename=channel.queueDeclare.getQueue();创建一个临时队列,名字随机的,队列没有持久化,断开消费者连接后,队列自动被删除。临时交换机没有持久化 ,
【
10.Fanout(发布订阅模式,扇出交换机):生产者将信息发送给fnout类型的交换机,不直接发送给队列,交换机与队列有一个routtingkey,可以实现一个消息被多个消费者消费。
此模式routtingkey相同与不相同,只要从该类型交换机获取数据,都能接收到。
消费者:
1.创建一个信道
2.创建一个队列(临时队列也可以)
3.创建一个交换机 channel.exchangeDeclare("exchangename",“fanout”)
4.绑定队列:channel.queueBind("queuename","exchangename","routtingkey")
5.等待接收消息
生产者:
1.创建一个信道
2.发布消息,channel.basicpublish("exchangename","routtingkey",其他属性,消息字节).
11.direct(路由模式,直接交换机):直接交换机,通过routtingkey获取数据。 与fanout创建一样。 只不过创建交换机时,类型为direct。 消费者获取消息,根据routtingkey的值获取对应的信息, 用于分发。
12.Topic**:(主题交换机):使用最广:routtingkey可以用* 或者#代替, *代表一个占位符,#代表多个。 eg: *.key1.* --> 任意字符.key1.任意字符,只要满足这个就可以获取信息。 lazy.# -->lazy.任意长度字符,只要满足这个就可以获得信息。
当一个队列绑定键是#时,那么这个队列将接收所有数据,有点像Fanout。 如果队列没有出现# /* 那么就是direct。
】
13.死信队列(交换机类型为direct):消费者发生异常,将消息放到死信队列中。 死信的三种来源:1.消息被拒绝,2消息TTL过期,3队列达到最大长度,成为死信队列。 成为死信队列之后,消费者需要通过死信交换机获取死信队列的消息。
消息过期模式:设置发送消息过期时间,消费者宕机,生产者还在发消息,消息过期后,被发送到死信队列,其他消费者从死信队列中获取消息
1.分析: 生产者发消息被 消费者A接收或者拒收。拒收的消息发送到死信队列中,被消费者B获取消息。
步骤: 1. A有两个队列和两个交换机 ,一个正常队列,一个死信队列。 一个正常交换机,一个死信交换机。
2. 在声明正常队列时,设置map的参数, 在map中传递map.put("x-dead-letter-exchange",DIED_EXCHANGE);//死信交换机,
map.put("x-dead-letter-routing-key","diedkey");//死信队列routtingkey。
3.B通过死信交换机获取消息。
TTL模式: 在生产者中AMQP.BasicProperties properties=new AMQP.BasicProperties().builder().expiration("10000").build(); 设置消息过期时间,在发布消息中将对象填进去。
队列最大长度:在消费者中,声明队列时,参数传值,map.put("x-max-length",5);//超过5条数据就将超过的消息放入死信队列中。
消息被拒模式: 在消费者中,在成功消费的接口中,手动应答,拒绝消息。channel.basicReject(”拒收的消息“,是否重新发回队列)
14:延迟队列(direct交换机):基于死信的延迟队列
队列设置过期时间,生产者发送消息之后,消息过期发给死信队列。 基于死信的延迟缺陷: 消息只能顺序进入死信队列,比如a消息延迟20s,b延迟2s,a比b先发送,那么需要a延迟之后,才会到b。
基于springboot实现:
思路: 创建两个及以上的正常队列, 创建一个死信队列。 一个正常交换机,一个死信交换机。
正常队列需要绑定死信交换机及正常队列消息的ttl过期时间。
步骤: 1.创建一个配置类,在配置类中@bean队列和交换机,一个队列一个@bean,一个交换机一个@bean。
2. 创建队列 return QueueBuilder.durable(NQUEUE2).withArguments(map).build(); --------------也可以 return new queue(name). with();创建队列
3.创建交换机 return new DirectExchange(DEXCHANGE);
4.绑定交换机与队列;需要获取创建的队列与交换机。with后面为routingkey
public Binding nbinding(@Qualifier("n1") Queue nqueue,
@Qualifier("nchange") DirectExchange nexchange){
return BindingBuilder.bind(nqueue).to(nexchange).with("n1");
}
15.x-delayed-message类型的交换机:基于插件的延迟队列
需要在linux中下载插件。 作用:弥补延迟队列基于死信的缺陷,队列中的消息只要过期了就直接进入死信队列中,不分顺序。
思路: 一个队列,一个x-delayed-message类型的交换机。
步骤:1.创建一个配置类,在配置类中@bean交换机与队列。队列正常操作(设置消息过期时间)。 交换机需要CustomExchange自定义类型的创建。
2.创建交换机:public CustomExchange delayexchange(){return new CustomExchange(DELAY_EXCHANGE,"x-delayed-message",true,false,map); 一共五个参数},
map中需要传入 map.put("x-delayed-type","direct");//延迟类型为direct。
3.生产者发送消息,以地址的方式发送,自己想怎么发就怎么发
4.消费者接收消息,@RabbitListener(queues="队列名"),在方法上用,并在形参写上Message message参数来接收消息。
设置ttl过期时间可以用correlationData的setTime方法设置过期时间。 也可以直接在队列中args用x-message-ttl设置
16.发布确认高级(基于springbbot):1.当生产者发送消息给交换机,交换机没有接收到,然后将没有接收到的消息反馈给生产者。 配置文件添加:【spring.rabbitmq.publisher-confirm-type=correlated】
步骤:1. 创建一个配置类,配置交换机(direct)和队列并绑定。
2.创建一个生产者,CorrelationData correlationData=new CorrelationData("1")--设置发送消息的id号。
rabbitTemplate.convertAndSend(CONFIMEXCHANGE,"confirmroutingkey",msg,correlationData);发送消息
3.函数回调,新建一个类实现RabbitTemplate.ConfirmCallback,并添加类进ioc容器, @PostConstruct
public void init(){
rabbitTemplate.setConfirmCallback(this);
}。将当前回调函数类设置为接口的回调函数
4.在回调函数类中public void confirm(CorrelationData correlationData, boolean ack, String cause){} 判断打印接收的消息,
一为消息的id(correlation.getid()),二为消息的状态,接收true,未接受,false,3为失败的原因。
2.当生产者发送消息给routingkey,routingkey'不存在,造成消息发送失败,信道将消息返回给发布者。配置文件添加:【publisher-returns: true】开启routingkey返回函数
步骤:1.在函数回调的3中再实现RabbitTemplate.ReturnsCallback,将当前类设置为回调函数。rabbitTemplate.setReturnsCallback(this)
2.重写方法returnedMessage() ---有过时的和不过时的,都要重写。 --如果routingkey错误,就会执行该方法。
执行的顺序:1.当调用了发布消息的方法后,会将发布消息的信息封装为一个id,需要自己new一个correlationData对象,如果不传入值,则默认id为correlationData的ip地址,
然后回调函数根据该id来返回结果集。
***【重要】:只要开启了发布确认,即实现了交换机接口的RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback,并重写对应方法后,该项目的所有rabbitmq发送消息时都会进行消息发送失败的返回。
备份交换机: 1.当交换机出现错误,消息会被转发到另一个交换机上,再备份交换机上创建一个备份队列用于发送消息,一个报警队列,用于接收发现不可路由的消息。
步骤:1.再确认发布中,在创建确认交换机时,绑定备份交换机。
ExchangeBuilder exchangeBuilder=ExchangeBuilder.directExchange(CONFIMEXCHANGE).durable(true).alternate(BACKEXCHANGE);
return (DirectExchange) exchangeBuilder.build();
2.创建一个备份交换机以及备份队列以及报警队列。并绑定
3.监听报警队列中的信息,并打印。 只要消息在正常交换机中没有被发送,那么消息就会进入备份交换机,然后监听报警队列就会发现该消息,并不是消费该消息。
17.幂等性:用户对统以操作发器的一次请求或者多次请求结果是一致的,不会因为多次点击产生副作用。 eg:支付成功,返回结果网络波动。防止消息被重复消费 --利用redis操作。 setnx
18.优先级队列(0-255):priority,默认再队列中的消息是先进先出,先进的先被消费, 如果消息设置优先级的话, 会在队列中依据优先级对消息重新排列,数值越大越优先。
1.创建优先级队列,在map参数中添加:map.put("x-max-priority","优先级的最大值x" ) --设置完之后, 优先级0-x。
2.发送消息设置优先级:在发布消息的其他参数上设置,如果是信道发送消息: AMQP.BasicProperties properties=new AMQP.BasicProperties().builder().priority(优先级).build; 然后将该properties传给发布消息的参数。
如果是rabbitTemplate发送消息:在发布消息中最后一个函数式接口的参数中用拉姆达表达式设置消息优先级:
eg: rabbitTemplate.convertAndSend("priorityexchange","prioritykey",
msg.getBytes(StandardCharsets.UTF_8),message -> {
message.getMessageProperties().setPriority(6);
return message;
});
优先级需要让消息堆积,然后再被消费者消费才起作用,不然消息一发送就被消费者消费了,体现不出来优先级。
19.惰性队列:消息保存在内存中还是在磁盘上。正常情况下消息保存在内存中,在惰性中,消息保存在磁盘上。 使用在消费者宕机。
map.put("x-queue-mode","lazy")。
20.rabbitmq集群:
21:镜像队列(mirro):队列备份,在集群中,用于在一个结点机上创建的队列如果宕机之后,可能会产生消息的丢失,此时就需要镜像队列将随机在其他节点上创建一个一样的备份队列。 宕机之后可以利用该队列获取消息, 且又会在其他节点上备份一个队列。
22.高并发负载均衡:大量请求涌入,通过 nginx配置,实现负载均衡。
【注意】:rabbbitmqTemplate的rabbitTemplate.receiveAndConvert(queue) 接收消息时,不会调用成功或者失败回调函数。
RabbitMQ:是一个消息中间件,接收并转发消息。
主要知识点:轮训分发 ------》消息应答------》发布确认(单个,批量,异步批量) ----》交换机(三种) -----》死信队列-----》基于死信的延迟队列------》基于插件的延迟队列(x-delayed-message类型的交换机)----》
发布确认高级-----》备份交换机备份队列与警告队列------》幂等性----》优先级队列-----》惰性队列-----》rabbitmq集群。
-

浙公网安备 33010602011771号