2.启用管理插件
rabbitmq-plugins enable rabbitmq_management
3.启动RabbitMQ
systemctl start rabbitmq-server.service
systemctl status rabbitmq-server.service
systemctl restart rabbitmq-server.service
systemctl stop rabbitmq-server.service
4.查看进程
ps -ef | grep rabbitmq
测试
- 关闭防火墙:systemctl stop firewalld.service
- 在web浏览器中输入地址:http://虚拟机ip:15672/
输入默认账号密码: guest : guest,guest用户默认不允许远程连接
增加自定义账号
l 添加管理员账号密码:rabbitmqctl add_user admin admin
l 分配账号角色:rabbitmqctl set_user_tags admin administrator
l 修改密码:rabbitmqctl change_password admin 123456
l 查看用户列表:rabbitmqctl list_users
使用新账号登录,成功界面
管理界面标签页介绍
l overview:概览
l connections:无论生产者还是消费者,都需要与RabbitMQ建立连接后才可以完成消息的生产和消费,在这里可以查看连接情况
l channels:通道,建立连接后,会形成通道,消息的投递获取依赖通道。
l Exchanges:交换机,用来实现消息的路由
l Queues:队列,即消息队列,消息存放在队列中,等待消费,消费后被移除队列。
端口:
l 5672:rabbitMq的编程语言客户端连接端口
l 15672:rabbitMq管理界面端口
l 25672:rabbitMq集群的端口
卸载
l rpm -qa | grep rabbitmq
l rpm -e rabbitmq-server
RabbitMQ⼯作⽅式
简单模式
⼀个队列只有⼀个消费者
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPQ01LII-1667358715428)(D:\桌面\bug集\扩展\typora-img\image-20221026084217054.png)]
⼯作模式
多个消费者监听同⼀个队列
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2cvgK5Mh-1667358715430)(D:\桌面\bug集\扩展\typora-img\image-20221026084415757.png)]
订阅模式
⼀个交换机绑定多个消息队列,每个消息队列有⼀个消费者监听
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nttdKtgE-1667358715430)(D:\桌面\bug集\扩展\typora-img\image-20221026084246153.png)]
路由模式
⼀个交换机绑定多个消息队列,每个消息队列都有⾃⼰唯⼀的key,每个消息队列有⼀个 消费者监听
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yo8NShI3-1667358715431)(D:\桌面\bug集\扩展\typora-img\image-20221026084322881.png)]
Direct(精准匹配交换机)
消息中的路由键(routing key)如果和 Binding 中的 binding key 一致
交换器就将消息发到对应的队列中。路由键与队列名完全匹配,如果一个队列绑
定到交换机要求路由键为“dog”,则只转发 routing key 标记为“dog”的消
息,不会转发“dog-puppy”,也不会转发“ddg. guard”等等。它是完全匹配、
单播的模式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KxuF7AWz-1667358715431)(D:\桌面\bug集\扩展\typora-img\image-20221025171450132.png)]
Fanout(类似广播模式交换机 1对多)
每个发到 fanout 类型交换器的消息都会分到所有绑定的队列上去。fanout
交换器不处理路由键,只是简单的将队列绑定到交换器上,每个发送到交换器的
消息都会被转发到与该交换器绑定的所有队列上。很像子网广播,每合子网内的
主机都获得了一份复制的消息。fanout 类型转发消息是最快的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e1JRGmyX-1667358715432)(D:\桌面\bug集\扩展\typora-img\image-20221025173137591.png)]
Topic (对routingkey进行匹配的交换机 1对多)
topic交换器迪过模式匹配分_己消息的路由键属性,将路由键和某个模式进
行
-匹配,此时队列需要绑定到一个模式上。它将路由键和绑定键的字符串切分成
单词,这些单词之间用点隔开。它同样也会识别两个通配符:符号“#”和符号
“*”。并匹配0个或多个单词,“ * ”匹配不多不少一个单词。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H5WLuJHK-1667358715432)(D:\桌面\bug集\扩展\typora-img\image-20221025193827720.png)]
创建队列
public class SendMsg {
public static void main(String[] args) throws Exception{
String msg = "Hello HuangDaoJun!";
Connection connection = ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//定义队列(使⽤Java代码在MQ中新建⼀个队列)
//参数1:定义的队列名称
//参数2:队列中的数据是否持久化(如果选择了持久化)
//参数3: 是否排外(当前队列是否为当前连接私有)
//参数4:⾃动删除(当此队列的连接数为0时,此队列会销毁(⽆论队列中是否还有数据))
//参数5:设置当前队列的参数
注意:
1、声明风列时,这个从列名称如果已经存在则放弃声努,如果队列不存在网会声明一个新的队列
2、从列名可以软值任意,但是要与消息接收时完全一致
3、这行代码是可有可无的但是一定要在发送消息前确认队列名已经存在在RabbitMQ中,否则就会出现问题//channel.queueDeclare("queue7",false,false,false,null);
//参数1:交换机名称,如果直接发送信息到队列,则交换机名称为""
//参数2:⽬标队列名称
//参数3:设置当前这条消息的属性(设置过期时间 10)
//参数4:消息的内容
注意:队列名必须要与接收时完全一致
channel.basicPublish("","queue1",null,msg.getBytes());
System.out.println("发送:" + msg);
channel.close();
connection.close();
}
}
创建direct类型交换机
public class SendMsg {
public static void main(String[] args) throws Exception{
String msg = "Hello HuangDaoJun!";
Connection connection =ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
//队列
channel.queueDeclare("queue7",false,false,false,null);
/**
声明一个交换机
参数1为交换机的名称歌值在意
参数2为交换机的类型软值为 direct、fanout、topic、headers
参数3为是否为持久化交换机
注意:
1、声明交换机时如关这个交换机巫存在必会放弃声明,如果交换机不存在则声明交换机
2、这个代码是可有可无的但是在使用前必须要确保这个交换机被声明
*/
channel.exchaneDeclare("jhj","direct",ture);
/**
绑定交换机
将队列绑定到交换机
参数1为队列的名称
参数2为交换机名称
参数3为湾息的RoutingKey(就是Bindingkey
注意:
1、在进行队列和交换机绑定时必须要确保交换机和队列已经成功的声明
*/
channel.queueBind("queue7","jhj","directRoutingkey");
/*
发送消原到指定的队列
参数1为交换机名称
参数2为消原的RoutingKey如果这个消息的RoutingKey和某个队列与交 换机绑定的RoutingKey一致那么这个消京就会发送的指定的队列中
*/ channel.basicPublish("jhj","queue1",null,msg.getBytes());
System.out.println("发送:" + msg);
channel.close();
connection.close();
}
}
创建fanout类型交换机
public class SendMsg {
public static void main(String[] args) throws Exception{
String msg = "Hello HuangDaoJun!";
Connection connection =ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.exchaneDeclare("fanoutExchanget","fanout",ture);
channel.basicPublish("fanoutExchanget","",null,msg.getBytes());
System.out.println("发送:" + msg);
channel.close();
connection.close();
}
}
fanout 消息接收
/**
由于Fanout类型的交换机的消息时类似于广播的模式,它不需要绑定RoutingKey而又可能会有农多个消费来接收这个交换列中的数格,团此我们创建队列时要船舰一个随机的队列名称
没有参数的queueDecLare方法会创建一个名字为随机的一个队列
这个队列的数据时非持久化
是排外的(同时最多只九许有一个消费若盈听当前队列)
白动删除的 当没有任何消费者监听队列时这个队列会自动删除
getQueue()方法用于获软这个随机的队列名
*/
//ring name = channel.queueDeclare().getQueue();
//channel.queueBind(name,“fanoutExchanget”,“”);
创建topic交换机
public class SendMsg {
public static void main(String[] args) throws Exception{
String msg = "Hello HuangDaoJun!";
Connection connection =ConnectionUtil.getConnection();
Channel channel = connection.createChannel();
channel.exchaneDeclare("topicExchanget","fanout",ture);
/**参数2:⽬标队列名称
看routingkey绑定的是那个如果是aa那么就往aa里面发消息其他的收不到 */
channel.basicPublish("fanoutExchanget","aa",null,msg.getBytes());
System.out.println("发送:" + msg);
channel.close();
connection.close();
}
}
事务消息
事务消息与数据库的事务类似,只是MQ中的消息是要保证消息是否会全部发送成功
防止去失消息的一种策略。
RabbitMQ有两种方式来解决这个可题:
1.通过AMQP提供的事务机制实现;
2.使用发送者确认模式实现;
事务的使用
事务的实现主要是对信道(Channel)的设置,主要的方法有三个
- channel. txSelect()声明启动事务模式;
- channel. txCommint()提交事务;
- channel. txRollback()回滚事务;
消息的发送者确认模式(同事务一样)
Confirm 发送方确认模式使用和事务类似,也是通过设置 Channel 进行发送方确认的
最终达到确保所有的消息全部发送成功·
Confirm的三种实现方式:
方式一:channel. waitForConfirms ()普通确认模式
channel.confirmSelect();//启动消息确认模式
/**普通确认模式: 它只确认最后一次发送的消息。
*/
channel. waitForConfirms ();
方式二:channel. waitForConfirmsOrDie ()批量确认模式
channel.confirmSelect();//启动消息确认模式
/*批量消息确认,它会同时向服务中确认之前通道中发送的所有的消息是否已经全部成功写入、这个方法没有任何返回值,如果服务器中有一条消息没有能够成功或向服务器发送确认服务时服务不可访问都被认定为消息确认失败,可能有消息没有发送成功,我们需要进行消息的补发。
如果无法向服务器获软确认信息那么方法就会抛出InterruptedException异常,这时就需要承发消息到队列vaitForConfirmsOrDie方法可以指定一个参数timeout 历于等待服务器的确认时/可,如果超过这个时间也会抛出异常,表示确认失败需要补发消息。
注意:
批量消息确认的速度比普通的消泉确认要快,一旦出现了消息剂发的情况,我们不能确定具体是那条消息没有完成发送,需要将本次的发送的所有消息全部进行补发。
**/
channel. waitForConfirmsOrDie ();
方式三:channel. addConfirmListener()消息的发送者确认模式
/*异步消息确认监听器,需要在发送消息前启动
**/
channel.addConfirmListener(new ConfirmListener(){
//消原确认以后的回调方法
//参数1: 为被确认的消息的编号 从1 开始自动递增用于标记当前是第几个消息
//参教2 为当前消息是否同时确认的了多个
//注意 :如果参数2rue如表示本次确水同时确认了多条消息,消息等于当前参数1 (消息编号)的所有消息
//全部被确认如果为aLse 网表示只确认多了当前编号的消息
public void handleAck(long l,boolean b)throws IOEXception {
System.out.println("消息被确认了---消息编号:"+1+"是否确认了多条:"+b)
}
//消息没有确认的回调方法
//如果这个方法荧执行表示当莎的消原没有被确认需要进行消原补发
//参数1为没有被确认的消息的编号从 1开始白动递增用于标记当前是第儿个消息
//参数2为当前消息是否同时没有确认多个
//注意 :如果参数2为true 则表示小于当前编号的所有的消息可能都没有发送成功需要进行消息的补发
//如果参数2为aLse则表示当前编号的消息没法发送成功需要进行补发
public void handleNack(long l,boolean b)throws IOException {
}
});
消费者确认模式(重)
basicAck():用于肯定确认,multiple 参数用于多个消息确认。
basicRecover():是路由不成功的消息可以使用recovery重新发送到队列中。
basicReject():是接收端告诉服务器这个消息我拒绝接收不处理,可以设盖是否放回到队列中
不是去掉,而月只能一次拒绝一个消息,官网中有明确说明不能批量拒绝消息,为解决批量
拒绝消息才有 basicNack。
basicNack():可以一次拒绝N条消息,客户端可以设置basicNack方法的multiple参数为true。
try {
connection=factory.newConnection();
channel=connection.createchannel();
channel.queueDeclare("confirmQueue",true, false, false, null)
channel.exchangeDeclare( "directConfirmExchange", "direct",true); channel.queueBind("confirmQueue","directconfirmExchange","confirmRoutingKey");
/*
接收消息
参数2为消息的确认机制,true表示白动消息确认,确认以后消息会从队列中被移除,当读取完消息以后就会自动确认消息
注意
1、如果我们只是接收的消原但是还没有来得处塑,当前应用就朗炭或在进行处理的时候例如像数据库中
写数据但是数据库这时不可用,那么由于消息是白动确认的那么这个消急就会在接收完成以后自动从队列中
被州除,这就会丢失消息
*/
channel.basicConsume( "confirmQueue", true,"",new DefaultConsumer(channe1){
public void handleDelivery
(String consumerTag,Envelope envelope,AMQP.BasicProperties propeerties, //获取当前消息是否被接收过一次 false表示没有接收过反之接收过
System.out.println(envelope.isRedeliver());
//获取当前内部类中的通道
channel c = this.getChannel();
if(envelope.isRedeliver()){
String message=new String(body);
System.out.println("消费者 处理了消息--"+message);
//获软消息的编号,我们需要根格消屈的编号来确认消原
Long tag = envelope.getDeliverTag();
//手动确认消息,确认以后表示当前消息已经成功处理了,需要从对列中移除掉
//这个方法应该在当前湾息的处塑程序全部完成以后执行
//参数1 消息的编号
//参数2 为是否确认多个、如果数rue 网表示需要确胡小等于当剪编号的所有消层,faLse就是单个确认值确认当煎消息
// c.basicAck(tag,true);
}else{
//程序到厂这华表示这个消层之前已经碳楼收过箭要进行防南复处班
//例如查询效据库中是否已经添加」记录或已经修改过了记录
//如果经过判新这条没有被处理完成购需要童新处理消氙然后确认掉这条消是
//加果已务外碑过广贝百袭确认消原即可不务要进行其他外理操作
c.basicAck(tag,true);
}
/ *
注意: 如果启动了事务,而消息消费之确认模式为手动确认那么必须要提交事务否则即使调用了确认方法、那么方法也不会从队列中被移除
**/
c.txCommit();
});
Rabbitmq 集群
普通模式
启动多个rabbitmq 比如说a机器与b机器,往a通道写入数据,从b机器读取数据,我们需要b机器与b机器建立一个临时通道来读取a机器的数据,如果a机器突然宕机了,那么我们就读取不到消息了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MJTUnvT1-1667358715434)(D:\桌面\bug集\扩展\typora-img\image-20221027110146607.png)]
镜像模式(高可用模式)
把需要的队列做成镜像模式存在于多个节点,数据 Rabbitmq 的HA方案.该模式解决了上述问题,其实质和普通模式的不同之处在于,消息实体会主动在镜像节点间同步而不会在 consumer 取数据时临时拉取.该模式带来的副作用也很明显,除了降低系统生能意外如果镜像队列过多,加之有大量的消息进入,集群内部的网各带宽将会被这种司步用讯大大消耗掉,所以在对可靠性要求较高的场合中适用.
配置集群
需要在host文件与另一台机器进行绑定
.coolick 文件必须一致
将某个 RabbitMQ加入到某个服务器节点
rabbitmqctl stop_app
rabbitmqctl join cluster rabbit@A
rabbitmgctl start_app