rabbitMQ入门

  • rabbitMQ整体架构模型是什么样子的
  • rabbitMQ消息是如何流转的
  • rabbitMQ安装与使用
  • 命令行与管控台
  • rabbitMQ消息生产与消费(Java)
  • rabbitMQ交换机详解
  • rabbitMQ队列 绑定 虚拟主机 消息

JMX

rabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,rabbitMQ使用的就是Erlang语言来编写的,并且rabbitMQ是基于AMQP协议。

通过不同调用api将消息发送到队列服务器中,然后后端可以调用api消费队列服务器中的消息,形成一个生产者与消费者模型

rabbitMQ优点:

  1. 开源,性能优秀,稳定性保障
  2. 提供可靠性消息投递模式confirm
  3. 与springAMQP完美整合,API丰富
  4. 集群模式丰富,基于表达式配置,HA模式,镜像队列模型
  5. 在保证数据不丢失的前提下做到高可用性,高可靠性

Q:rabbitMQ高性能的原因

  1. Erlang语言最初在于交换机领域的架构模式,这使得rabbitMQ在blocker之间进行数据交互,数据同步的性能是十分优秀的
  2. Erlang的优点就是:Erlang有着与原生socket一样的延时。

APC 基于socket,socket延时十分低,主要的考量目标就是延时以及响应  关注MQ的延时怎么样 性能怎么样 吞吐量怎么样。

 

什么是AMQP高级消息队列协议

AMQP定义:是具有现代特征的二进制协议,是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。

换句话说AMQP协议就是一个规范,在编写MQ时候只要依据MQ规范编写即可。

virtual host虚拟主机 (比较上层的路由)

exchange 交换机(AMQP核心)生产者直接将消息投递到exchange中,经历三个过程

  1. 查找服务器,建立链接,设置地址以及端口号
  2. 投递到哪一个virtual host
  3. 然后就是投递到哪一个exchange

rabbitMQ最主要目的就是解耦和的。

consumer  application是从message Queue中获取数据的,然后整个MQ最主要的一点就是exchange与message queue之间的绑定关系,不然的话message queue无法从exchange中获取消息。

AMQP核心概念

  1. Server:又称为broker,接受客户端的链接,实现AMQP实体服务
  2. connection:连接,应用程序与broker的网络连接
  3. channel:网络通道,几乎所有的操作都是在channel中进行的,channel是进行消息读写的通道。客户端可建立多个channel,每个channel代表一个会话任务。
  4. message:消息  服务器和应用程序之间传递的数据,由properties和body组成的。properties可以对消息进行修饰,比如消息的优先级,延时等高级特性;body则就是消息体内容。
  5. virtual host:虚拟地址,用于逻辑隔离,最上层的消息路由。一个virtual host中可以有若干个exchange和queue,同一个virtual host里面不能有相同名称的exchange或者是queue。
  6. 这是一个逻辑概念,并非像物理隔离那样子,将每一个数据大小都标明,使用逻辑隔离,可能会导致每个数据库内存大小并不一致。
  7. exchange:交换机,接收消息,根据路由键转发消息到绑定的队列中。队列与exchange中有绑定关系
  8. binding:exchange和Queue之间的虚拟连接,binding可以包含routing key
  9. routing key:一个路由规则,虚拟机可以用它来确定如何路由一个指定的信息
  10. Queue:也称message queue,消息队列,保存消息并将它们转发给消费者

 rabbitMQ整体架构是什么样子

 生产者只需要关系将消息放置在哪一个exchange就可以了,不需要关心具体投放在哪一个队列

消费者只需要关系消息是在哪一个队列就可以了,不需要关心从哪里来的。

绑定就是路由。

     exchange是有路由策略的,就是所谓的rootingkey,我们发送message时候需要携带两个重要的点,第一个就是选择哪一个exchange,第二个就是携带rootingkey。然后通过exchange和队列建立绑定关系,借助你的rootingkey将消息路由到你指定的队列之中,消费者只需要监听该队列就可以了。

 

rabbitMQ安装

erlang安装包,rabbit基于erlang开发的。

安装Linux必要的包。

下载rabbit必须安装包

配置文件修改

 

最好使用3.6x版本。

Q:如何在实际生产环境中,更新rabbitMQ服务器版本,更改集群。

  1. 技术调研,版本是否需要更新,性能是否更好。
  2. 高性能的测试。
  3. 上线时候,也需要进行灰度上线。100个节点首先只发布1 2个节点,在生产环境中先跑几个月观察一下。然后就是再整体上线。

有一点注意的就是erlang版本需要与rabbitMQ相互对应。在Linux中下载rabbitMQ时候,首先下载erlang和密钥包。

在实际工作中,通常都是配置导出,然后再配置导进就可以了。

消息生产与消费

  1. ConnectionFactory:获取链接工厂 。 需要配置相关信息,MQ节点的地址端号。
  2. Connection:一个链接
  3. Channel:数据通信信道,可发送和接收消息。
  4. Queue:具体的消息存储队列
  5. Producer&Consumer生产和消费者。

在编写过程之前,需要在pom.xml导入相关依赖的包。在<dependency>

<groupId>com.rabbitmq</groupId>

<artifactId>amqp-client</artifactId>

<version>3.6.5</version>

</dependency>中进行依赖配置。

Producer

//1.创建一个ConnectionFactory,并进行配置。
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory .setHost("192.168.11.76");
connectionFactory .setPort(5672);//默认端口号
connectionFactory .setVirtualHost("/");//设置虚拟主机  这个虚拟主机是在管控台自己设置的

//2.通过连接工厂创建连接
Connection  connection = connectionFactory .newConnection();

//3.通过Connection创建一个Channel  这个是通信最关键的一部分。
Channel  channel  = connection.createChannel();

//4.通过 channel发送数据,消息组成部分主要就是props和body,props主要就是修饰消息一些附加属性。
//指定exchange和rootingKey   传送的是bytes数组
//channel.basicPublish(exchange,routingKey,props,body);
String msg = "SADAS00";
channel.basicPublish("","test001",null,msg.getBytes());

//5.记得关闭相关连接
channel.close();
connection.close();

 consumer

//1.创建一个ConnectionFactory,并进行配置。
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory .setHost("192.168.11.76");
connectionFactory .setPort(5672);//默认端口号
connectionFactory .setVirtualHost("/");//设置虚拟主机  这个虚拟主机是在管控台自己设置的

//2.通过连接工厂创建连接
Connection  connection = connectionFactory .newConnection();

//3.通过Connection创建一个Channel  这个是通信最关键的一部分。
Channel  channel  = connection.createChannel();


//最少有一个队列存放信息,然后consumer才能监听这个队列,接收消息,消费消息
//4.声明一个队列  通过channel操作
//channel.queueDeclare(queue,durable,exclusive,autoDelete,arguments);
//queue是队列名字,可以是一个String
//durable是否持久化,持久化的好处就是服务器即使重启,这个队列也是不会丢失
//exclusive表示独占的方式,在某些场景下还是很有好处的,比如说顺序消费,独占就是表示这个队列只有这
//个channel可以监听,其他的连接都不可以监听,就是相当于加了一把锁。目的就是保证消息的顺序消费
//有一种情况就是消费者是集群ABC,通过负载均衡可能使A消费3条,B消费3条,C消费4条,但是不能保证ABC消费信息的进度是有顺序的,就是谁要在谁前面先完成的问题。使用独占方式。
//autoDelete  就是队列如果没有绑定关系的时候,就会自动删除
//arguments扩展参数

channel.queueDeclare("test001",true,false,false,null);


//5.创建消费者,表示这个消费着是建立在channel这个连接之上的。
QueueingConsuumer  queueingConsuumer = new QueueingConsuumer(channel);


//6.设置channel,channel.basicConsumer(queue,autoAck,callback);
//autoAck是否自动签收,blocker和消费端进行监听数据,发送数据,消费数据。当blocker发送消息给消费端时候,消费端就会马上发送一个Ack消息,表示该消息已经收到。可以设定手工Ack
//callback就是代表消费者对象

channel,channel.basicConsumer("test001",true,queueingConsuumer);


//获取消息    Delivery就是对MQ进行了一个Java级别的封装
//Delivery delivery = queueingConsuumer.nextDelivery();//如果没有消息的话就阻塞

while(true){
Delivery delivery = queueingConsuumer.nextDelivery();
String msg = new String(delivery.getBody);
System.err.println("消费端"+msg);
//这里有一个重要的对象 Envelope  envelope = delivery.getEnvelope();
//可以获取到关于队列信息,自己手写Ack时候,也要通过这个对象实现。
}

有一个值得注意的是,一开始要先运行一次消费端代码,这个目的就是为了创建(声明相对应的队列)。

Q:rootingKey  生产者与消费者之间的队列是通过如何来绑定的。

A:虽然你没有设置exchange,但是只要生产者中channel设定的rootingKey值与消费者队列名称相同的话,就可以自动绑定了。

因为rabbitMQ在生产者发消息的时候,必须要指定一个exchange,如果你不指定exchange或者exchange为空的话,他就会走第一个exchange,AMQP default的exchange,它的路由规则就是 根据你的rootingKey来查找MQ队列中是否有相对应的名字。如果有就把消息路由到指定的队列。

 

exchange交换机

exchange:接收消息,并且根据路由键转发消息所绑定的队列。

name:名称

type:交换机属性 direct  fanout headers

durability 是否需要持久化

Auto Delete 当最后一个绑定到exchange上的队列删除后,自动删除该exchange

internal:当前exchange是否用于rabbitmq内部使用 默认是false

arguments:扩展参数 用于扩展amqp协议自制定化使用

direct exchange

 所有发送到direct exchange 的消息被转发到routekey中指定的queue

 注意:direct模式可以使用rabbitmq自带的exchange:default exchenge,所以不需要将exchenge进行任何绑定操作,消息传递时候,routekey必须完全匹配时才会被队列接收,否则消息会被抛弃。

//1.创建一个ConnectionFactory,并进行配置。
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory .setHost("192.168.11.76");
connectionFactory .setPort(5672);//默认端口号
connectionFactory .setVirtualHost("/");//设置虚拟主机  这个虚拟主机是在管控台自己设置的


connectionFactory.
//2.通过连接工厂创建连接
Connection  connection = connectionFactory .newConnection();

//3.通过Connection创建一个Channel  这个是通信最关键的一部分。
Channel  channel  = connection.createChannel();

//4.通过 channel发送数据,消息组成部分主要就是props和body,props主要就是修饰消息一些附加属性。
//指定exchange和rootingKey   传送的是bytes数组
//channel.basicPublish(exchange,routingKey,props,body);
String exchangeName = "test_direct_exchange";
String routingKey = "test.direct";
//5.发送
String msg = "SADAS00";
channel.basicPublish(exchangeName ,routingKey ,null,msg.getBytes());

//5.记得关闭相关连接
channel.close();
connection.close();
//1.创建一个ConnectionFactory,并进行配置。
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory .setHost("192.168.11.76");
connectionFactory .setPort(5672);//默认端口号
connectionFactory .setVirtualHost("/");//设置虚拟主机  这个虚拟主机是在管控台自己设置的

//网络中断后,设置是否重连
connectionFactory.setAutomaticRecoveryEnable(true);
//设置重连的时间
connectionFactory.setNetworkRecoveryInterval(3000); 

//2.通过连接工厂创建连接
Connection  connection = connectionFactory .newConnection();

//3.通过Connection创建一个Channel  这个是通信最关键的一部分。
Channel  channel  = connection.createChannel();


//最少有一个队列存放信息,然后consumer才能监听这个队列,接收消息,消费消息
//4.声明一个队列  通过channel操作
//channel.queueDeclare(queue,durable,exclusive,autoDelete,arguments);
//queue是队列名字,可以是一个String
//durable是否持久化,持久化的好处就是服务器即使重启,这个队列也是不会丢失
//exclusive表示独占的方式,在某些场景下还是很有好处的,比如说顺序消费,独占就是表示这个队列只有这
//个channel可以监听,其他的连接都不可以监听,就是相当于加了一把锁。目的就是保证消息的顺序消费
//有一种情况就是消费者是集群ABC,通过负载均衡可能使A消费3条,B消费3条,C消费4条,但是不能保证ABC消费信息的进度是有顺序的,就是谁要在谁前面先完成的问题。使用独占方式。
//autoDelete  就是队列如果没有绑定关系的时候,就会自动删除
//arguments扩展参数


//声明交换机以及队列


String exchangeName = "test_direct_exchange";
String exchangeType = "direct";
String queueName = "test_direct_queue";
String routingKey = "test.direct";
channel.exchangeDeclre(exchangeName ,exchangeType ,true,false,false,null);
channel.queueDeclare(queueName ,false,false,false,null);


//绑定交换机以及队列
channel.queueBind(exchangeName,queueName ,routingKey );

//5.创建消费者,表示这个消费着是建立在channel这个连接之上的。
QueueingConsuumer  queueingConsuumer = new QueueingConsuumer(channel);


//6.设置channel,channel.basicConsumer(queue,autoAck,callback);
//autoAck是否自动签收,blocker和消费端进行监听数据,发送数据,消费数据。当blocker发送消息给消费端时候,消费端就会马上发送一个Ack消息,表示该消息已经收到。可以设定手工Ack
//callback就是代表消费者对象

channel,channel.basicConsumer(queueName ,true,queueingConsuumer);


//获取消息    Delivery就是对MQ进行了一个Java级别的封装
//Delivery delivery = queueingConsuumer.nextDelivery();//如果没有消息的话就阻塞

while(true){
Delivery delivery = queueingConsuumer.nextDelivery();
String msg = new String(delivery.getBody);
System.err.println("消费端"+msg);
//这里有一个重要的对象 Envelope  envelope = delivery.getEnvelope();
//可以获取到关于队列信息,自己手写Ack时候,也要通过这个对象实现。
}

direct:必须保证routingkey名称完全一致才可以。如果想通过queueName匹配到routingKey的话需要重新设置一下生产者端的routingKey。

 

 

fanout exchange

  1. 不处理任何的路由键,所以你的路由器是fanout模式的话,设置不设置routingkey也没有所谓。它只需要简单的将队列绑定到交换机上就可以了。
  2. fanout交换机转发消息是最快的,因为不需要进行任何的匹配。
  3. 发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。

个人理解:就是一个交换机可以绑定多个队列,一个队列可以被多个交换机绑定,找到相对应的交换机时候,就通过routingKey进行匹配,找到相对应的队列,rabbitMQ默认的路由规则就是通过queueName匹配的,其他都是通过routingKey匹配的  熟称路由规则。

 

Topic Exchange

  1. 所有发送到topic exchange 的 消息被转发到所有关心routingkey中指定的queue上
  2. exchange将routingkey和某一个topic进行模糊匹配,此时队列需要绑定一个topic

 

 

关系之间的重新设置的话,就要进行解锁绑定。

bingding-绑定

exchange和exchange,queue之间的连接关系(可以通过不同的routingkey将消息重exchange转发到另一个exchange)

binding中可以包含routingKey或者参数

 

queue 

消息队列,实际存储消息数据

durability:是否持久化  durable 是 transient 否

auto delete 代表当最后一个监听被移除后,该queue会自动删除

 

Message消息

服务器和应用程序之间传递的数据

本质上就是一段数据,由properties 和 payload (body)组成

常用属性:delivery mode  headers(自定义属性) 送达模式(持久化或者非持久化  自己自定义 自己获取)

其他属性

content_type  content-_encoding  priority

是不是可以通过设定优先级来确保优先级高的数据先被消费,优先级低的数据后被消费

不能的,集群模式,一定没有办法保证消息按照一定的序列被消费的,这里的话就涉及了顺序消息的概念。

correlation_id  reply_to  expiration  message_id

correlation_id在业务中可能作为唯一的id使用,业务和timestamp拼接。 ACK  消息路由 幂等  都会用到

reply_to  做重回队列,就是消息失败后,可以返回到哪一个队列

expiration表示消息过期的时间。

timestamp  jtype  userid  appid  cclusterid

下面主要是props部分的设置。

 

virtual host-虚拟主机

虚拟地址,用于进行逻辑隔离,最上层的消息路由

一个virtual host 里面可以有若干个exchange和queue

同一个virtual host 里面不能有相同名称的exchange或queue

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值