rabbitmq基础知识

rabbitmq基础知识

背景:

  RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现。AMQP 的出现其实也是应了广大人民群众的需求,虽然在同步消息通讯的世界里有很多公开标准(如 COBAR的 IIOP ,或者是 SOAP 等),但是在异步消息处理中却不是这样,只有大企业有一些商业实现(如微软的 MSMQ ,IBM 的 Websphere MQ 等),因此,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等联合制定了 AMQP 的公开标准。

  RabbitMQ是由RabbitMQ Technologies Ltd开发并且提供商业支持的。该公司在2010年4月被SpringSource(VMWare的一个部门)收购。在2013年5月被并入Pivotal。其实VMWare,Pivotal和EMC本质上是一家的。不同的是VMWare是独立上市子公司,而Pivotal是整合了EMC的某些资源,现在并没有上市。

工作原理:

组成部分说明如下:
Broker:消息队列服务进程,此进程包括两个部分:Exchange和Queue。
Exchange:消息队列交换机,按一定的规则将消息路由转发到某个队列,对消息进行过虑。

Queue:消息队列,存储消息的队列,消息到达队列并转发给指定的消费方。
Producer:消息生产者,即生产方客户端,生产方客户端将消息发送到MQ。
Consumer:消息消费者,即消费方客户端,接收MQ转发的消息。
消息发布接收流程:
-----发送消息-----
1、生产者和Broker建立TCP连接。
2、生产者和Broker建立通道。
3、生产者通过通道消息发送给Broker,由Exchange将消息进行转发。
4、Exchange将消息转发到指定的Queue(队列)

----接收消息-----
1、消费者和Broker建立TCP连接
2、消费者和Broker建立通道
3、消费者监听指定的Queue(队列)
4、当有消息到达Queue时Broker默认将消息推送给消费者。
5、消费者接收到消息。

交换机的类型:

fanoutfanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。

direct:direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中

topic前面提到的direct规则是严格意义上的匹配,换言之Routing Key必须与Binding Key相匹配的时候才将消息传送给Queue,那么topic这个规则就是模糊匹配,可以通过通配符满足一部分规则就可以传送。它的约定是:

routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”

binding key与routing key一样也是句点号“. ”分隔的字符串

binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)  

headerheaders类型的Exchange不依赖于routing key与binding key的匹配规则来路由消息,而是根据发送的消息内容中的headers属性进行匹配。
在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。
该类型的Exchange没有用到过(不过也应该很有用武之地),所以不做介绍。

 

rabbitmq的工作模式:

工作队列模式:

work queues与入门程序相比,多了一个消费端,两个消费端共同消费同一个队列中的消息。
应用场景:对于 任务过重或任务较多情况使用工作队列可以提高任务处理的速度。
测试:
1、使用入门程序,启动多个消费者。
2、生产者发送多个消息。
结果:
1、一条消息只会被一个消费者接收;
2、rabbit采用轮询的方式将消息是平均发送给消费者的;
3、消费者在处理完某条消息后,才会收到下一条消息。

发布订阅模式:
1、每个消费者监听自己的队列。
2、生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队列都将接收
到消息

 使用场景:当用户注册之后要发送邮箱和验证码

roulingkey 路由模式:
1、每个消费者监听自己的队列,并且设置routingkey。
2、生产者将消息发给交换机,由交换机根据routingkey来转发消息到指定的队列。

topic 路由模式:
1、每个消费者监听自己的队列,并且设置带统配符的routingkey。
2、生产者将消息发给broker,由交换机根据routingkey来转发消息到指定的队列。

 

header模式

header模式与routing不同的地方在于,header模式取消routingkey,使用header中的 key/value(键值对)匹配
队列。
案例:
根据用户的通知设置去通知用户,设置接收Email的用户只接收Email,设置接收sms的用户只接收sms,设置两种
通知类型都接收的则两种通知都有效。

 

ConnectionFactory、Connection、Channel

 

  ConnectionFactory、Connection、Channel都是RabbitMQ对外提供的API中最基本的对象。Connection是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory为Connection的制造工厂。
  Channel是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。

 

  Connection就是建立一个TCP连接,生产者和消费者的都是通过TCP的连接到RabbitMQ Server中的,这个后续会再程序中体现出来。

 

  Channel虚拟连接,建立在上面TCP连接的基础上,数据流动都是通过Channel来进行的。为什么不是直接建立在TCP的基础上进行数据流动呢?如果建立在TCP的基础上进行数据流动,建立和关闭TCP连接有代价。频繁的建立关闭TCP连接对于系统的性能有很大的影响,而且TCP的连接数也有限制,这也限制了系统处理高并发的能力。但是,在TCP连接中建立Channel是没有上述代价的。

至于这个这些操作可以看看之前的代码

 

分析:

1 在实际开发中,应该通常使用topic模式。也就是通配符模式,可以根据通配符模式来进行匹配,这样自定义规则就可以了,

2 当一个生产者多个消费者时候,消费者会是采用轮询的方式进行消费不会重复消费

3 rabbitmq的各种模式对应相对应的交换机,topic模式是一种通配符模式这个模式跟activemq中的topic消息时存在区别,在activemq中,topic是一种类似udp消息模式,可以多个消费者同时消费一个消息,但是不能确定百分百都消费,

  会存在有些消费米有被消费,在rabbitmq中不存在这种模式

4  消息重发;当消费者接受到消息之后,会进行消费,那么如果这个时候出现异常了,自动签收就会存在消息消费了,那么订单消息就会丢失,所以应该采用手动回签在代码里面避免这个情况存在

5 百分百可靠性投递消息:设置手动回签,或者采用延时队列发送消息。

6 可以使用rabbitmq进行分布式事物处理,采用最终一致性来避免分布式事物

 

posted @ 2019-03-25 10:38 动手的程序员 阅读( ...) 评论( ...) 编辑 收藏
<think>我们正在创建一个关于Java RabbitMQ基础知识学习的Markdown文件。RabbitMQ是一个开源的消息代理和队列服务器,用于在分布式系统之间传递消息。在Java中使用RabbitMQ,我们通常使用它的Java客户端库。 我们将按照以下结构组织内容: 1. RabbitMQ简介 2. 核心概念 3. Java客户端使用步骤 4. 示例代码(生产者、消费者) 5. 交换器类型 6. 队列和消息属性 7. 消息确认机制 8. 持久化 9. 常见问题 注意:在Markdown中,代码块使用三个反引号,并指定语言。 我们将参考用户提供的引用,但注意引用[1]是关于JVM元空间的,引用[2]是关于Java自增自减运算符的,与RabbitMQ无关,因此我们不会在内容中直接引用它们。 但是,由于系统要求引用的段落末尾要添加引用标识,而这里我们并没有使用这两个引用,所以我们不会添加。如果我们在内容中引用了其他资料,我们会添加引用标识。 下面开始生成Markdown内容。 </think>以下是关于 Java RabbitMQ 基础知识的 Markdown 文件框架,包含核心概念和代码实践: ```markdown # Java RabbitMQ 基础知识 ## 一、核心概念 ### 1. RabbitMQ 架构 ```plaintext +-------------+ +-------------+ +----------+ | Producer | ----> | Exchange | ----> | Queue | +-------------+ +-------------+ +----------+ | v +----------+ | Consumer | +----------+ ``` ### 2. 核心组件 - **Exchange**:消息路由中心(四种类型) - **Queue**:存储消息的缓冲区 - **Binding**:交换机和队列的连接规则 - **Channel**:TCP 连接中的虚拟通道 - **Connection**:与 RabbitMQ 服务器的 TCP 连接 ## 二、Java 客户端基础 ### 1. Maven 依赖 ```xml <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.16.0</version> </dependency> ``` ### 2. 生产者示例 ```java public class Producer { private final static String QUEUE_NAME = "hello"; public static void main(String[] args) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) { // 声明队列 (持久化/Durable) channel.queueDeclare(QUEUE_NAME, true, false, false, null); String message = "Hello RabbitMQ!"; // 发布消息 (持久化模式) channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes(StandardCharsets.UTF_8)); System.out.println(" [x] Sent: " + message); } } } ``` ### 3. 消费者示例 ```java public class Consumer { private final static String QUEUE_NAME = "hello"; public static void main(String[] args) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); // 声明队列(需与生产者一致) channel.queueDeclare(QUEUE_NAME, true, false, false, null); // 回调函数处理消息 DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received: " + message); // 手动ACK确认 channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); }; // 消费消息(关闭自动ACK) channel.basicConsume(QUEUE_NAME, false, deliverCallback, consumerTag -> {}); } } ``` ## 三、关键配置详解 ### 1. 交换机类型 | 类型 | 路由规则 | 使用场景 | |-------------|----------------------------------|-----------------------| | `Direct` | 精确匹配 RoutingKey | 点对点消息 | | `Fanout` | 广播到所有绑定队列 | 发布/订阅 | | `Topic` | 通配符匹配 RoutingKey | 多维度路由 | | `Headers` | 根据消息头属性匹配 | 复杂路由逻辑 | ### 2. 消息持久化 ```java // 队列持久化 channel.queueDeclare(QUEUE_NAME, true, false, false, null); // 消息持久化 channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, // ← 关键参数 message.getBytes()); ``` ### 3. 消息确认机制 - **自动 ACK**:`channel.basicConsume(QUEUE, true, ...)` - **手动 ACK**: ```java channel.basicConsume(QUEUE, false, ...); // 处理完成后手动确认 channel.basicAck(deliveryTag, multiple); ``` ## 四、最佳实践 1. **连接复用**:每个线程使用独立 Channel,共用 Connection 2. **资源释放**:确保关闭 Channel 和 Connection 3. **异常处理**:添加 `ShutdownListener` 监听连接中断 4. **QoS 控制**: ```java channel.basicQos(1); // 每次只处理一条消息 ``` > 完整项目示例:[rabbitmq-java-tutorial](https://github.com/rabbitmq/rabbitmq-tutorials/tree/master/java) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值