当前位置: 首页 > news >正文

中山网站建设如何工会网站群建设

中山网站建设如何,工会网站群建设,太仓网站制作书生,企业做网站设计的#x1f468;#x1f3fb;‍#x1f4bb; 热爱摄影的程序员 #x1f468;#x1f3fb;‍#x1f3a8; 喜欢编码的设计师 #x1f9d5;#x1f3fb; 擅长设计的剪辑师 #x1f9d1;#x1f3fb;‍#x1f3eb; 一位高冷无情的编码爱好者 大家好#xff0c;我是 DevO… ‍ 热爱摄影的程序员 ‍ 喜欢编码的设计师 擅长设计的剪辑师 ‍ 一位高冷无情的编码爱好者 大家好我是 DevOps 工程师 欢迎分享 / 收藏 / 赞 / 在看 这篇 RabbitMQ 教程为学习者提供了全面的内容从 RabbitMQ 的简介开始涵盖了消息中间件的概念、RabbitMQ 的安装与使用以及交换机、队列、路由键等相关概念的介绍。进一步深入教程探讨了 AMQP 协议、客户端开发向导以及消息的发送和消费方式。同时学习者还可以了解消息传输保障、高级特性如死信队列、延迟队列、优先级队列、RPC 实现等。此外教程还涵盖了 RabbitMQ 的管理、配置、运维、监控和集群管理等重要主题帮助学习者充分掌握 RabbitMQ 的应用。整篇教程丰富内容详实适合初学者和有经验的开发者参考学习。 全篇共 11 章9 万余字。本文第4章 RabbitMQ 进阶。 第4章 RabbitMQ 进阶 4.1 消息何去何从 本节将介绍 RabbitMQ 中消息的发送和接收过程并深入了解消息传递时的一些参数和特性。 4.1.1 mandatory参数 mandatory 参数是 RabbitMQ 的消息发送方法中的一个可选参数。它的作用是在消息无法被路由到任何队列时将消息返回给生产者而不是直接将消息丢弃或进入死信队列。 当生产者发送一条消息到交换机时如果交换机无法将消息路由到任何队列通常会将消息丢弃。但是如果在发送消息时设置了 mandatory 参数为 true那么当消息无法被路由到任何队列时RabbitMQ 会将消息返回给生产者。 要使用 mandatory 参数需要确保交换机和队列之间设置了合适的绑定关系。如果没有合适的绑定关系消息将会无法被路由到任何队列从而触发 mandatory 参数的效果。 处理无法路由的消息的方式取决于生产者对消息的处理需求 重发消息 在收到无法路由的消息后生产者可以选择重新发送该消息。这样可以尝试多次将消息路由到合适的队列直到成功为止。在重新发送消息之前可能需要进行一些额外的处理例如等待一段时间避免过于频繁地发送消息。记录日志 生产者可以选择记录日志并对无法路由的消息进行相应的记录。这样可以用于后续的排查和问题分析。丢弃消息 如果生产者确定无法路由的消息没有必要再进行重发或其他处理可以选择将该消息丢弃从而避免消息持续占用资源。 在实际应用中mandatory 参数的使用需要根据具体的业务需求来决定。如果消息的可靠性和处理可见性对业务至关重要可以考虑使用 mandatory 参数以便在消息无法被路由时及时进行处理。但是需要注意合理处理无法路由的消息避免无限制地重发或持续占用资源。 下面是使用 Java 客户端库发送带有 mandatory 参数的消息的示例 public class Producer {private static final String EXCHANGE_NAME myExchange;private static final String ROUTING_KEY myRoutingKey;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);String message Hello, RabbitMQ!;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().deliveryMode(2) // 持久化消息.build();// 发送带有mandatory参数的消息channel.basicPublish(EXCHANGE_NAME, invalidRoutingKey, true, properties, message.getBytes());System.out.println(Message sent with mandatory flag.);} catch (Exception e) {e.printStackTrace();}} } 在上面的示例中生产者发送了一条带有 mandatory 参数的消息并使用一个不存在的路由键invalidRoutingKey。由于该路由键没有绑定到任何队列消息将无法被路由到任何队列从而触发 mandatory 参数的效果。 4.1.2 immediate 参数 immediate 参数是 RabbitMQ 的消息发送方法中的另一个可选参数。它的作用是在消息无法立即被消费时将消息返回给生产者而不是直接将消息丢弃或进入死信队列。 当生产者发送一条消息到交换机时如果交换机无法将消息投递到任何队列例如没有消费者与该队列连接通常会将消息丢弃。但是如果在发送消息时设置了 immediate 参数为 true那么当消息无法立即被消费时RabbitMQ 会将消息返回给生产者。 要使用 immediate 参数需要确保交换机和队列之间设置了合适的绑定关系并且至少有一个消费者与队列连接。否则消息将无法立即被消费从而触发 immediate 参数的效果。 处理无法立即消费的消息的方式取决于生产者对消息的处理需求 重发消息 在收到无法立即消费的消息后生产者可以选择重新发送该消息。这样可以尝试多次将消息投递到合适的队列直到成功为止。在重新发送消息之前可能需要进行一些额外的处理例如等待一段时间避免过于频繁地发送消息。记录日志 生产者可以选择记录日志并对无法立即消费的消息进行相应的记录。这样可以用于后续的排查和问题分析。丢弃消息 如果生产者确定无法立即消费的消息没有必要再进行重发或其他处理可以选择将该消息丢弃从而避免消息持续占用资源。 在实际应用中immediate 参数的使用需要根据具体的业务需求来决定。如果消息的实时性和及时处理对业务至关重要可以考虑使用 immediate 参数以便在消息无法立即被消费时及时进行处理。但是需要注意合理处理无法立即消费的消息避免无限制地重发或持续占用资源。 下面是使用 Java 客户端库发送带有 immediate 参数的消息的示例 public class Producer {private static final String EXCHANGE_NAME myExchange;private static final String ROUTING_KEY myRoutingKey;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT);String message Hello, RabbitMQ!;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().deliveryMode(2) // 持久化消息.build();// 发送带有immediate参数的消息channel.basicPublish(EXCHANGE_NAME, invalidRoutingKey, true, false, properties, message.getBytes());System.out.println(Message sent with immediate flag.);} catch (Exception e) {e.printStackTrace();}} } 在上面的示例中生产者发送了一条带有 immediate 参数的消息并使用一个不存在的路由键invalidRoutingKey。由于该路由键没有绑定到任何队列消息将无法立即被消费从而触发 immediate 参数的效果。 4.1.3 备份交换机 备份交换机Backup Exchange是 RabbitMQ 中的一种特殊类型的交换机它的作用是为了确保消息的可靠传递。当消息无法被路由到合适的队列时备份交换机会接收这些消息并将它们路由到备份队列从而保证消息不会丢失。 备份交换机的用法可以通过以下步骤实现 定义备份交换机 首先你需要创建一个备份交换机。备份交换机是一个特殊类型的交换机它可以将无法被路由的消息路由到备份队列。创建备份队列 在定义备份交换机的同时你还需要创建一个备份队列。这个备份队列将用于接收无法被路由的消息。绑定备份交换机和备份队列 将备份队列与备份交换机进行绑定。这样当消息无法被路由到合适的队列时备份交换机会将消息发送到备份队列。 备份交换机的创建和绑定步骤通常是在 RabbitMQ 的管理界面进行配置。在界面中你可以创建备份交换机并定义备份队列然后将它们进行绑定。 使用备份交换机可以确保在消息无法被路由到合适的队列时消息不会丢失。这对于对消息传递的可靠性要求较高的场景非常有用例如在生产环境中确保消息不会丢失。 值得注意的是备份交换机只有在以下两种情况下才会被触发 当消息无法被路由到任何队列时。当消息在路由过程中遇到其他错误例如交换机无法传递消息。 使用备份交换机时你可以根据实际需求进行配置例如定义备份交换机的类型、备份队列的属性等以及在备份队列中处理无法路由的消息的逻辑。 需要注意的是备份交换机只能保证消息在无法被路由时不会丢失但并不能保证消息一定会成功被路由到队列中。因此仍然需要合理处理消息的确认和重试机制以确保消息的可靠传递。 4.2 过期时间TTL 在 RabbitMQ 中你可以为消息设置过期时间以确保一旦消息在指定的时间内未被消费就会自动被清理。这个特性可以帮助你处理那些需要在一定时间内被消费的消息避免消息长时间堆积而导致资源浪费。 为消息设置过期时间有两种方式 设置消息的过期时间 在发送消息时可以通过设置消息的过期时间属性来让消息在一定时间后自动被清理。过期时间是消息的一个属性单位是毫秒。当消息过期后RabbitMQ 会将其从队列中移除不再传递给消费者。设置队列的过期时间 另一种方式是设置队列的过期时间。你可以在创建队列时通过设置 x-message-ttl 参数来定义队列的过期时间。当设置了队列的过期时间后在消息被投递到队列后如果一定时间内没有被消费者消费那么该消息会被自动清理。 注意消息的过期时间和队列的过期时间是相互独立的如果同时设置了消息的过期时间和队列的过期时间以较短的那个时间为准。 下面是使用 Java 客户端库发送带有过期时间的消息的示例 public class Producer {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 声明队列并设置队列的过期时间为 10 秒单位毫秒channel.queueDeclare(QUEUE_NAME, false, false, false, arguments(x-message-ttl, 10000));String message Hello, RabbitMQ with TTL!;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().expiration(5000) // 设置消息的过期时间为 5 秒单位毫秒.build();// 发送带有过期时间的消息channel.basicPublish(, QUEUE_NAME, properties, message.getBytes());System.out.println(Message sent with TTL.);} catch (Exception e) {e.printStackTrace();}} } 在上面的示例中通过设置消息的过期时间属性expiration为 5000 毫秒即 5 秒和队列的过期时间参数x-message-ttl为 10000 毫秒即 10 秒消息和队列都将在一定时间后自动被清理。 需要注意的是设置过期时间并不能保证消息一定会在指定的时间内被清理。因为在 RabbitMQ 中清理过期消息是由消息的消费情况和队列的状态来决定的。如果队列一直没有被消费者消费或者消费者的消费速度很慢那么消息可能会在过期时间之后仍然存在在队列中。因此你仍然需要根据实际情况来合理设置过期时间并且使用适当的消息确认和消费策略来确保消息的及时清理。 4.2.1 设置消息的TTL 为消息设置过期时间可以通过两种方式来实现 设置消息的过期时间 在发送消息时可以通过设置消息的过期时间属性来让消息在一定时间后自动被清理。过期时间是消息的一个属性单位是毫秒。当消息过期后RabbitMQ 会将其从队列中移除不再传递给消费者。设置队列的过期时间 另一种方式是设置队列的过期时间。你可以在创建队列时通过设置 x-message-ttl 参数来定义队列的过期时间。当设置了队列的过期时间后如果一定时间内没有被消费者消费那么该消息会被自动清理。 注意消息的过期时间和队列的过期时间是相互独立的如果同时设置了消息的过期时间和队列的过期时间以较短的那个时间为准。 下面是使用 Java 客户端库发送带有过期时间的消息的示例 public class Producer {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 声明队列并设置队列的过期时间为 10 秒单位毫秒channel.queueDeclare(QUEUE_NAME, false, false, false, arguments(x-message-ttl, 10000));String message Hello, RabbitMQ with TTL!;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().expiration(5000) // 设置消息的过期时间为 5 秒单位毫秒.build();// 发送带有过期时间的消息channel.basicPublish(, QUEUE_NAME, properties, message.getBytes());System.out.println(Message sent with TTL.);} catch (Exception e) {e.printStackTrace();}} } 在上面的示例中通过设置消息的过期时间属性expiration为 5000 毫秒即 5 秒和队列的过期时间参数x-message-ttl为 10000 毫秒即 10 秒消息和队列都将在一定时间后自动被清理。 需要注意的是设置过期时间并不能保证消息一定会在指定的时间内被清理。因为在 RabbitMQ 中清理过期消息是由消息的消费情况和队列的状态来决定的。如果队列一直没有被消费者消费或者消费者的消费速度很慢那么消息可能会在过期时间之后仍然存在在队列中。因此你仍然需要根据实际情况来合理设置过期时间并且使用适当的消息确认和消费策略来确保消息的及时清理。 4.2.2 设置队列的TTL 在 RabbitMQ 中你可以为队列设置过期时间一旦队列在指定的时间内未被使用没有任何消费者连接到队列或没有进行任何消息的投递和消费就会自动被清理。这个特性可以帮助你处理那些可能在一段时间后不再需要的队列避免队列长时间占用资源。 要为队列设置过期时间可以在创建队列时使用参数 x-expires。这个参数指定了队列的过期时间单位是毫秒。当队列的过期时间到达后RabbitMQ 会自动将该队列删除同时也会删除与该队列相关的所有消息。 下面是使用 Java 客户端库创建带有过期时间的队列的示例 public class QueueExpiration {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 创建队列并设置过期时间为 30 秒单位毫秒channel.queueDeclare(QUEUE_NAME, false, false, false,arguments(x-expires, 30000));System.out.println(Queue with expiration created.);} catch (Exception e) {e.printStackTrace();}} } 在上面的示例中我们使用参数 arguments(x-expires, 30000) 来为队列设置过期时间为 30000 毫秒即 30 秒。一旦队列在 30 秒内未被使用没有消费者连接、没有消息投递和消费该队列将会被自动清理。 需要注意的是队列的过期时间只会在队列没有被使用的情况下生效。如果队列正在被消费者连接、有消息投递或消息正在被消费那么过期时间不会起作用。因此在设置队列过期时间时需要根据实际业务场景来选择合适的时间避免误删正在使用的队列。同时建议结合消费者的连接状态和消息的消费情况来合理设置队列的过期时间以确保队列能够按需自动清理。 4.3 死信队列 死信队列Dead Letter Queue简称DLQ是 RabbitMQ 中的一种特殊队列用于存储未能成功消费的消息。当消息无法被消费者正确处理时可以将该消息发送到死信队列以便进行进一步的处理、分析或延迟重试。 使用死信队列可以解决以下场景的问题 消息消费失败 当消费者无法成功处理消息时例如消费者抛出异常或处理超时你可以将该消息发送到死信队列。这样你就可以对消费失败的消息进行后续处理例如记录日志、进行分析或进行延迟重试。消息被拒绝 在某些情况下你可能会手动拒绝某些消息。例如消息的内容不符合预期或者你希望将某些特定的消息发送到死信队列以进行专门处理。通过将被拒绝的消息发送到死信队列你可以在之后对这些消息进行特殊处理。 使用死信队列的步骤如下 定义死信交换机 首先你需要创建一个死信交换机Dead Letter Exchange。死信交换机用于接收无法被消费者处理的消息并将这些消息路由到死信队列。定义死信队列 创建一个专门用于存储死信的队列即死信队列。该队列将接收从死信交换机路由过来的消息。绑定死信交换机和死信队列 将死信队列与死信交换机进行绑定以便将无法被消费者处理的消息路由到死信队列。配置消息的死信属性 在发送消息时可以通过设置消息的死信属性来指定该消息无法被消费时的处理方式。当消息无法被消费者正确处理时RabbitMQ 将会将这些消息发送到死信交换机并最终路由到死信队列。 通过使用死信队列你可以将未能成功消费的消息进行专门处理避免消息的丢失或无限循环重试。你可以在死信队列中进行日志记录、分析问题的原因、重新投递消息等操作。 需要注意的是死信队列的设置和使用需要根据具体的业务需求和场景来决定。你可以定义多个死信队列每个死信队列用于处理不同类型的消息或针对不同的消费者。同时结合消息的死信属性和消费者的确认机制可以更加灵活地处理未能成功消费的消息。 4.4 延迟队列 延迟队列是一种特殊的队列它可以实现消息的延迟处理。在 RabbitMQ 中常见的实现延迟队列的方式是使用消息的 TTLTime-To-Live和死信队列。通过结合这两个特性可以实现消息在一定时间后才会被消费从而实现消息的延迟处理。 下面介绍如何通过延迟队列实现消息的延迟处理 创建一个普通的队列 首先你需要创建一个普通的队列用于发送消息。设置消息的 TTL 在发送消息时通过设置消息的 TTL 属性来指定消息的过期时间。过期时间即消息在队列中的存活时间单位是毫秒。可以使用 expiration 属性来设置消息的 TTL。设置死信交换机和死信队列 接下来你需要创建一个死信交换机Dead Letter Exchange和一个死信队列Dead Letter Queue。这个死信队列将用于接收过期的消息。绑定死信交换机和死信队列 将死信队列与死信交换机进行绑定以便将过期的消息从死信交换机路由到死信队列。为普通队列设置死信属性 最后将普通队列的参数中的 x-dead-letter-exchange 设置为死信交换机的名称并将 x-dead-letter-routing-key 设置为死信队列的名称。这样当消息在普通队列中过期后会被发送到死信交换机并通过路由键被路由到死信队列。 通过上述步骤消息在发送到普通队列后会根据设置的 TTL 进行存活在过期时间到达后消息会变成“死信”被发送到死信队列进行进一步的处理。这样就实现了消息的延迟处理。 延迟队列的实现方式通过消息的 TTL 和死信队列的结合非常灵活且易于实现。你可以根据具体的业务需求来设置消息的过期时间从而实现不同时间段的延迟处理。需要注意的是延迟队列并不是 RabbitMQ 中的一个原生特性而是通过组合其他特性来实现的。因此在使用延迟队列时你需要确保消息的 TTL 和死信队列的配置都是正确的以确保延迟处理的效果能够符合预期。 4.5 优先级队列 在 RabbitMQ 中你可以通过使用优先级队列来优先处理重要的消息。优先级队列是一种特殊的队列它可以让具有更高优先级的消息被优先消费而低优先级的消息则被推迟处理。 注意优先级队列需要 RabbitMQ 3.5.0 或更高版本的支持。 要使用优先级队列需要注意以下几点 声明队列时指定 x-max-priority 参数 在声明队列时通过设置 x-max-priority 参数来指定队列支持的最大优先级。该参数的取值范围是 0 到 2550 表示不支持优先级255 表示支持最高优先级。默认情况下队列不支持优先级。设置消息的优先级 在发送消息时可以通过设置消息的优先级属性来指定消息的优先级。优先级越高的消息将被优先消费。消费者设置 basicQos 为了实现优先级队列的效果消费者需要设置 basicQos 方法并将 prefetchCount 参数设置为 1。这样可以确保消费者每次只处理一个消息从而避免低优先级的消息一直占用消费者。 下面是一个使用 Java 客户端库的示例代码演示如何创建优先级队列并发送具有不同优先级的消息 public class PriorityProducer {private static final String QUEUE_NAME priorityQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 声明队列并设置最大优先级为 10channel.queueDeclare(QUEUE_NAME, false, false, false,arguments(x-max-priority, 10));// 发送不同优先级的消息for (int priority 1; priority 10; priority) {String message Priority priority message;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().priority(priority).build();channel.basicPublish(, QUEUE_NAME, properties, message.getBytes());System.out.println(Sent: message);}} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们创建了一个优先级队列 priorityQueue并发送了 10 条具有不同优先级的消息。较高优先级的消息会被优先消费从而优先处理重要的消息。 需要注意的是RabbitMQ 会尽力确保较高优先级的消息能够被优先消费但并不保证所有情况下都能严格按照优先级顺序处理。在实际使用中你可能会遇到一些消息竞争的情况导致优先级较高的消息并不总是立即被消费。因此在使用优先级队列时需要合理设置消息的优先级并结合消费者的处理能力和消费速度来实现优先级队列的预期效果。 4.6 RPC 实现 远程过程调用Remote Procedure CallRPC是一种通信机制允许一个应用程序或服务调用另一个应用程序或服务的函数或方法就像调用本地函数一样。在 RabbitMQ 中可以使用请求-响应模式来实现 RPC其中客户端应用程序发送请求消息给服务端应用程序服务端处理请求后发送响应消息给客户端。 实现 RabbitMQ 的 RPC 可以分为以下步骤 定义请求队列和响应队列 客户端和服务端分别声明自己的请求队列和响应队列。客户端将请求发送到服务端的请求队列而服务端将响应发送到客户端的响应队列。发送请求消息 客户端发送一个包含请求数据的消息到服务端的请求队列并在消息属性中设置一个唯一的 correlationId关联 ID以便后续将响应与请求关联起来。接收请求消息并处理 服务端监听自己的请求队列一旦接收到客户端发送的请求消息就会处理请求并生成响应数据。发送响应消息 服务端将响应数据发送到客户端的响应队列并在消息属性中设置与请求消息相同的 correlationId以便客户端能够将响应与特定的请求对应起来。接收响应消息 客户端监听自己的响应队列一旦接收到服务端发送的响应消息并且 correlationId 与之前发送的请求消息相匹配就将响应数据取出并处理。 需要注意的是RPC 可能涉及到并发和超时处理。客户端在发送请求消息后需要等待一段时间来接收服务端的响应。为了确保能够正确匹配响应和请求通常会为每个请求维护一个 correlationId。另外为了处理超时情况客户端可以设置一个超时时间并在规定的时间内没有收到响应时进行处理。 下面是使用 Java 客户端库实现 RabbitMQ RPC 的简单示例 // 客户端发送请求 Channel channel connection.createChannel(); QueueingConsumer consumer new QueueingConsumer(channel); channel.basicConsume(replyQueueName, true, consumer);String correlationId UUID.randomUUID().toString(); AMQP.BasicProperties props new AMQP.BasicProperties.Builder().correlationId(correlationId).replyTo(replyQueueName).build();channel.basicPublish(, requestQueueName, props, message.getBytes());// 等待响应 while (true) {QueueingConsumer.Delivery delivery consumer.nextDelivery();if (delivery.getProperties().getCorrelationId().equals(correlationId)) {String response new String(delivery.getBody());break;} } // 服务端处理请求并发送响应 Channel channel connection.createChannel(); channel.queueDeclare(requestQueueName, false, false, false, null); channel.queueDeclare(replyQueueName, false, false, false, null);channel.basicConsume(requestQueueName, false, (consumerTag, delivery) - {String message new String(delivery.getBody());String correlationId delivery.getProperties().getCorrelationId();// 处理请求并生成响应String response processRequest(message);// 发送响应到响应队列AMQP.BasicProperties props new AMQP.BasicProperties.Builder().correlationId(correlationId).build();channel.basicPublish(, delivery.getProperties().getReplyTo(), props, response.getBytes());channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false); }); 以上示例展示了一个简单的 RabbitMQ RPC 的实现其中客户端发送请求消息到服务端服务端处理请求并发送响应消息给客户端。在实际使用中你可能还需要处理异常、超时等更复杂的情况。 4.7 持久化 在 RabbitMQ 中为了确保消息在服务器重启后不丢失你可以将交换机、队列和消息进行持久化。持久化的过程包括将交换机和队列声明为持久化的并将消息标记为持久化的。这样即使 RabbitMQ 服务器重启持久化的交换机、队列和消息也能够恢复并继续处理。 下面介绍如何将交换机、队列和消息进行持久化 将交换机和队列声明为持久化的 在声明交换机和队列时需要将 durable 参数设置为 true表示将交换机和队列声明为持久化的。持久化的交换机和队列将会被保存到磁盘上即使 RabbitMQ 服务器重启它们也能够恢复。将消息标记为持久化的 在发送消息时需要将消息的 deliveryMode 属性设置为 2表示将消息标记为持久化的。持久化的消息将会被保存到磁盘上即使 RabbitMQ 服务器重启它们也能够恢复。 下面是使用 Java 客户端库的示例代码演示如何将交换机、队列和消息进行持久化 public class PersistentProducer {private static final String EXCHANGE_NAME myExchange;private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 声明持久化的交换机channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, true);// 声明持久化的队列channel.queueDeclare(QUEUE_NAME, true, false, false, null);// 绑定队列到交换机channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, myRoutingKey);// 发送持久化的消息String message Persistent message;AMQP.BasicProperties properties new AMQP.BasicProperties.Builder().deliveryMode(2) // 将消息标记为持久化的.build();channel.basicPublish(EXCHANGE_NAME, myRoutingKey, properties, message.getBytes());System.out.println(Sent: message);} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们将交换机 myExchange 和队列 myQueue 声明为持久化的并将消息标记为持久化的。这样即使 RabbitMQ 服务器重启交换机、队列和消息都能够得到恢复不会丢失。 需要注意的是虽然持久化能够确保交换机、队列和消息在服务器重启后不丢失但仍然不能保证消息百分之百的可靠性。在某些情况下持久化的消息可能仍然会丢失例如在消息刚刚投递到磁盘但尚未写入时发生服务器崩溃。为了更加可靠地处理消息你还可以考虑使用备份队列、复制等高可用性和持久性的机制。 4.8 生产者确认发布确认 生产者确认机制Publisher Confirms是 RabbitMQ 提供的一种可靠性保证机制它确保消息成功发送到 RabbitMQ 服务器。通过使用生产者确认机制你可以在消息发送后得到服务器的确认从而可以确定消息是否已经成功投递到队列中。 在 RabbitMQ 中生产者确认机制是通过 AMQP 协议实现的。当生产者启用生产者确认机制后每次发送一条消息生产者会等待 RabbitMQ 服务器发送一个确认acknowledgment回执。如果收到确认回执表示消息已经被 RabbitMQ 接收并成功投递到队列中如果超过一定的时间确认超时时间生产者仍未收到确认回执则会认为消息发送失败可以选择重新发送消息。 要使用生产者确认机制需要注意以下几点 开启生产者确认模式 在发送消息前需要调用 confirmSelect() 方法将生产者设置为确认模式。添加确认监听器 通过 addConfirmListener() 方法添加一个确认监听器ConfirmListener来监听确认回执。在 handleAck() 方法中你可以处理成功投递的消息在 handleNack() 方法中你可以处理发送失败的消息。确认超时处理 在 handleNack() 方法中可以根据业务需求选择是否重新发送消息或者将失败的消息写入日志或存储起来进行后续处理。 下面是使用 Java 客户端库的示例代码演示如何使用生产者确认机制 public class PublisherConfirmsProducer {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 开启生产者确认模式channel.confirmSelect();// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 添加确认监听器channel.addConfirmListener(new ConfirmListener() {Overridepublic void handleAck(long deliveryTag, boolean multiple) {System.out.println(Message with delivery tag deliveryTag successfully delivered.);}Overridepublic void handleNack(long deliveryTag, boolean multiple) {System.out.println(Message with delivery tag deliveryTag failed to be delivered.);}});// 发送消息String message Hello, RabbitMQ!;channel.basicPublish(, QUEUE_NAME, null, message.getBytes());System.out.println(Sent: message);// 等待确认回执channel.waitForConfirmsOrDie();} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们使用 confirmSelect() 开启了生产者确认模式并添加了一个确认监听器来处理确认回执。在发送消息后我们使用 waitForConfirmsOrDie() 方法等待确认回执确保消息成功发送到 RabbitMQ 服务器。 使用生产者确认机制能够大大提高消息的可靠性确保消息不会因为网络故障、服务器故障或其他异常情况而丢失。因此在需要保证消息传递可靠性的场景中建议使用生产者确认机制。 4.8.1 事务机制 在 RabbitMQ 中事务机制是一种确保消息发送的原子性和可靠性的方法。使用事务机制可以将一组消息操作封装成一个事务在事务提交成功后这组消息要么全部成功发送到 RabbitMQ 服务器要么全部失败从而确保消息的原子性和可靠性。 使用事务机制需要注意以下几点 开启事务模式 在发送消息前需要调用 txSelect() 方法将通道设置为事务模式。事务模式下通道会处于 select 状态表示事务已开启。发送消息 在开启事务模式后通道会记录发送的所有消息但这些消息并未实际发送到 RabbitMQ 服务器。提交事务 在发送完一组消息后通过调用 txCommit() 方法来提交事务。如果事务提交成功则表示这组消息已经成功发送到 RabbitMQ 服务器如果事务提交失败则表示这组消息发送失败可以选择进行后续处理。回滚事务 在发送消息的过程中如果发生了错误或者不希望将消息发送到服务器可以调用 txRollback() 方法来回滚事务。回滚事务会取消之前发送的所有消息这些消息不会被 RabbitMQ 服务器处理。 需要注意的是使用事务机制会带来一定的性能开销。在事务提交时通道会阻塞直到事务处理完成这可能会导致较低的吞吐量。因此在性能要求较高的情况下可以考虑使用生产者确认机制Publisher Confirms来代替事务机制以提高消息的可靠性。 下面是使用 Java 客户端库的示例代码演示如何使用事务机制 public class TransactionalProducer {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 开启事务模式channel.txSelect();// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 发送消息String message Hello, RabbitMQ!;channel.basicPublish(, QUEUE_NAME, null, message.getBytes());System.out.println(Sent: message);// 提交事务channel.txCommit();System.out.println(Transaction committed successfully.);} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们使用 txSelect() 开启了事务模式并发送了一条消息。然后通过调用 txCommit() 提交事务将消息发送到 RabbitMQ 服务器。如果在发送消息的过程中发生了错误可以调用 txRollback() 方法来回滚事务消息不会被发送。 总结来说事务机制是一种简单可靠的消息发送方式可以确保消息的原子性和可靠性。但由于事务可能会带来性能开销因此在实际使用中需要根据具体的业务需求和性能要求来选择是否使用事务机制。如果需要更高性能的消息确认方式可以考虑使用生产者确认机制。 4.8.2 发送方确认机制 发送方确认机制Publisher Confirms是 RabbitMQ 提供的一种高性能的消息确认机制用于确保消息成功发送到 RabbitMQ 服务器。通过使用发送方确认机制生产者可以在发送消息后异步地等待 RabbitMQ 服务器的确认回执从而实现更高效的消息可靠性保证。 使用发送方确认机制需要注意以下几点 开启发送方确认模式 在发送消息前需要调用 confirmSelect() 方法将通道设置为发送方确认模式。发送方确认模式下通道会处于 confirm 状态。添加确认监听器 通过 addConfirmListener() 方法添加一个确认监听器ConfirmListener来监听确认回执。在 handleAck() 方法中你可以处理W成功投递的消息在 handleNack() 方法中你可以处理发送失败的消息。异步等待确认 在发送消息后不需要阻塞通道等待确认回执而是在后台异步地等待确认。你可以继续发送其他消息或处理其他逻辑。处理确认回执 当收到确认回执时handleAck() 方法会被调用你可以在其中处理成功投递的消息。如果未收到确认回执或收到了 nacknegative acknowledgmenthandleNack() 方法会被调用你可以在其中处理发送失败的消息。 下面是使用 Java 客户端库的示例代码演示如何使用发送方确认机制 public class PublisherConfirmsProducer {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 开启发送方确认模式channel.confirmSelect();// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 添加确认监听器channel.addConfirmListener(new ConfirmListener() {Overridepublic void handleAck(long deliveryTag, boolean multiple) {System.out.println(Message with delivery tag deliveryTag successfully delivered.);}Overridepublic void handleNack(long deliveryTag, boolean multiple) {System.out.println(Message with delivery tag deliveryTag failed to be delivered.);}});// 发送多条消息for (int i 0; i 10; i) {String message Message i;channel.basicPublish(, QUEUE_NAME, null, message.getBytes());System.out.println(Sent: message);}// 异步等待确认回执if (!channel.waitForConfirms()) {System.out.println(Some messages were not delivered.);} else {System.out.println(All messages were successfully delivered.);}} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们使用 confirmSelect() 开启了发送方确认模式并添加了一个确认监听器来处理确认回执。在发送多条消息后我们使用 waitForConfirms() 方法异步等待确认回执并根据返回结果判断消息是否全部成功发送到 RabbitMQ 服务器。 使用发送方确认机制能够实现高效的消息可靠性保证尤其在消息量较大的场景下相比使用事务机制发送方确认机制更加高效。因此在生产者需要保证消息的可靠性时推荐使用发送方确认机制。 4.9 消费端要点介绍 消费端在 RabbitMQ 中是消息的接收者它负责从队列中获取消息并进行处理。在消费端开发过程中有一些重要的概念和注意事项需要了解 消息分发 在多个消费者同时监听同一个队列时RabbitMQ 会将消息均匀地分发给每个消费者这个过程称为消息分发。消息分发采用的是轮询的方式即每个消费者轮流获取消息确保消息在消费者之间均匀分配。如果消费者数量超过队列中消息的数量某些消费者可能不会收到消息。如果你希望所有消费者都能收到相同的消息可以使用交换机的 fanout 类型将消息广播给所有队列和消费者。消息顺序性 在 RabbitMQ 中同一个队列中的消息保持了一定的顺序即消息的先后顺序和发送的顺序一致。但当有多个消费者同时消费一个队列中的消息时由于消息分发的特性消费者之间可能处理的消息顺序不同。如果需要保证消息的严格顺序性可以使用单个消费者来消费队列中的消息或者使用共享队列的方式来处理消息确保消息按照先后顺序被处理。弃用 QueueingConsumer 在 RabbitMQ 的早期版本中常常使用 QueueingConsumer 类来接收消息。但是官方不再推荐使用 QueueingConsumer因为它不支持自动确认消息的功能容易导致消息丢失。取而代之的是使用 DefaultConsumer 类它提供了更好的可靠性和性能。DefaultConsumer 允许使用自动确认消息或手动确认消息从而确保消息被正确处理。 以下是使用 Java 客户端库的示例代码演示如何使用 DefaultConsumer public class ConsumerExample {private static final String QUEUE_NAME myQueue;public static void main(String[] args) {ConnectionFactory factory new ConnectionFactory();factory.setHost(localhost);try (Connection connection factory.newConnection();Channel channel connection.createChannel()) {// 声明队列channel.queueDeclare(QUEUE_NAME, false, false, false, null);// 创建消费者DefaultConsumer consumer new DefaultConsumer(channel) {Overridepublic void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body) throws IOException {// 处理收到的消息String message new String(body, UTF-8);System.out.println(Received: message);// 手动确认消息防止消息丢失channel.basicAck(envelope.getDeliveryTag(), false);}};// 消费消息将自动确认设置为 false表示手动确认消息channel.basicConsume(QUEUE_NAME, false, consumer);// 等待接收消息Thread.sleep(5000);} catch (Exception e) {e.printStackTrace();}} } 在上述示例中我们使用 DefaultConsumer 类来创建消费者并手动确认收到的消息确保消息被正确处理。同时我们不推荐使用 QueueingConsumer而是使用更现代的 DefaultConsumer 类。 4.9.1 消息分发 不同类型的交换机和队列会对消息分发产生影响而实现消息的负载均衡可以通过合理地设计交换机和队列来实现。 不同类型的交换机对消息分发的影响 Fanout 交换机 Fanout 交换机会将所有收到的消息广播给所有与它绑定的队列即消息会被复制发送给所有消费者实现了消息的广播效果。这种交换机对于消息分发不产生影响所有绑定的队列都会收到相同的消息。Direct 交换机 Direct 交换机根据消息的路由键Routing Key将消息发送到与之匹配的队列。如果一个交换机绑定到多个队列并且使用不同的路由键进行绑定那么消息将根据路由键的匹配规则被发送到相应的队列实现了消息的选择性发送。Topic 交换机 Topic 交换机将消息根据匹配的模式发送到不同的队列。它支持通配符 # 和 *允许进行复杂的路由键匹配。通过合理设置交换机和队列的绑定键可以实现消息的灵活分发。 不同类型的队列对消息分发的影响 单一队列 当只有一个队列绑定到交换机时所有的消息都会被发送到这个队列中实现了消息的集中处理。多个队列 当有多个队列绑定到同一个交换机时交换机会根据不同的绑定键将消息分发到不同的队列中实现了消息的分流处理。通过合理设置不同队列的消费者数量可以实现消息的负载均衡。 实现消息的负载均衡需要考虑以下几点 使用多个消费者 将多个消费者同时监听同一个队列RabbitMQ 会将消息均匀地分发给每个消费者实现消息的负载均衡。多个队列与消费者数量匹配 如果有多个队列绑定到同一个交换机并且这些队列的消费者数量相同RabbitMQ 会根据队列绑定键的匹配规则将消息均匀地分发给不同队列从而实现消息的负载均衡。使用多个交换机 可以根据消息的特性将消息发送到不同类型的交换机中然后根据实际需求将队列绑定到相应的交换机上实现更灵活的消息分发和负载均衡。动态增加/减少消费者 根据消息的处理能力和系统的负载情况动态地增加或减少消费者数量实现根据实际负载情况的动态负载均衡。 综上所述通过合理设计交换机和队列的绑定关系以及增加多个消费者并动态调整消费者数量可以有效地实现消息的负载均衡提高系统的吞吐量和性能。 4.9.2 消息顺序性 处理消息的顺序性问题是在多个消费者同时消费同一个队列的情况下保证消息的先后顺序正确确保消息被有序处理。在 RabbitMQ 中由于消息的分发是轮询方式消费者之间可能会处理不同顺序的消息。为了实现消息的有序处理可以考虑以下方法 单个消费者 最简单的方法是只让一个消费者消费队列中的消息。这样消息就会按照先后顺序被一个消费者依次处理实现了消息的有序性。不过这种方式会导致消息的处理速度较慢可能无法充分利用多个消费者的并发处理能力。共享队列 可以使用多个消费者共享同一个队列来处理消息。在这种方式下每个消息只会被一个消费者处理但是消费者之间会并发地处理不同的消息。这样可以保证消息的有序性并充分利用多个消费者的并发处理能力。消费者串行化处理 在多个消费者共享同一个队列的情况下可以将消息的处理逻辑设计为串行化处理即每个消费者只处理一个消息然后再将消息传递给下一个消费者。这样可以确保消息的先后顺序正确。有序队列和消息分组 可以使用多个队列来实现消息的有序处理。将消息按照一定规则进行分组并将同一组消息发送到同一个队列中。然后每个队列由一个消费者进行处理确保每个队列中的消息按照顺序被处理。这样就可以实现消息的有序处理。 需要注意的是在实际应用中消息的顺序性可能会因为网络延迟、消费者处理时间等因素而产生一定的偏差。因此对于需要绝对严格的消息顺序性要求可能需要在业务层面进行额外的处理如使用分布式锁或全局顺序ID等机制。 总结来说处理消息的顺序性问题可以采用单个消费者、共享队列、消费者串行化处理、有序队列和消息分组等方法。具体选择哪种方式取决于业务需求和性能要求需要综合考虑系统的并发处理能力和消息顺序性的要求。 4.9.3 弃用 QueueingConsumer QueueingConsumer 是 RabbitMQ 早期版本中使用的消费者类用于从队列中接收消息。然而官方不再推荐使用 QueueingConsumer因为它存在一些弊端和限制。以下是 QueueingConsumer 的弊端 阻塞式接收消息 使用 QueueingConsumer 接收消息时消费者线程会被阻塞直到接收到消息为止。这种阻塞式的接收方式会导致消费者无法同时处理多个任务或消息降低系统的并发处理能力。无法实现自动消息确认QueueingConsumer 无法实现自动消息确认机制即消费者无法自动确认消息的处理完成需要手动调用 basicAck 方法来确认消息。这可能会导致消息处理失败或丢失因为没有及时确认消息会使得消息重新排队或被丢弃。可靠性问题QueueingConsumer 不能保证消息的可靠性因为消息的确认和重发机制都需要手动处理。如果在消费过程中出现异常或消费者崩溃消息可能会丢失或重复处理无法实现消息的可靠传递。 为了克服 QueueingConsumer 的弊端官方推荐使用 Channel 类来替代它。Channel 类是 RabbitMQ 客户端库中的一个重要组件提供了更灵活、高效和可靠的消息处理能力。使用 Channel 类可以实现以下优点 非阻塞式接收消息 使用 Channel 类接收消息时可以通过异步回调方式来处理消息消费者线程不会被阻塞。这样可以提高系统的并发处理能力使得消费者可以同时处理多个任务或消息。自动消息确认Channel 类支持自动消息确认机制即消费者可以自动确认消息的处理完成无需手动调用确认方法。这确保了消息的可靠传递减少了错误和消息丢失的风险。可靠性和异常处理Channel 类提供了更强大的异常处理和可靠性机制。通过设置合适的确认模式、错误处理策略以及消息重发机制可以保证消息的可靠性和系统的稳定性。更好的性能和扩展性Channel 类的设计更加灵活和高效能够处理更多的并发请求。它也更适合于大规模的分布式系统并能够与其他组件进行集成和扩展。 综上所述由于 QueueingConsumer 存在的弊端和限制官方推荐使用 Channel 类来代替它。Channel 类提供了更多的功能和灵活性能够更好地满足消息处理的需求并提供了更高的可靠性和性能。 4.10 消息传输保障 保障消息在传输过程中的可靠性和一致性是在消息队列中非常重要的一项任务。RabbitMQ 提供了一些机制来确保消息的可靠传输和处理下面介绍几种常用的方法 生产者确认机制 生产者确认机制是指生产者发送消息后等待 RabbitMQ 确认消息已经成功接收和处理的机制。这样可以确保消息已经安全地送达到 RabbitMQ 服务器防止消息丢失。生产者确认机制通过 ConfirmCallback 来实现在消息发送后可以通过设置 confirmSelect() 启用确认模式然后通过回调函数获取确认结果。持久化 RabbitMQ 允许将交换机、队列和消息设置为持久化即将它们的状态写入磁盘防止在 RabbitMQ 服务器重启后数据丢失。通过在声明交换机和队列时设置 durable 参数为 true以及在发布消息时设置消息的持久化属性可以保障消息的持久化和数据的一致性。事务机制 RabbitMQ 支持事务机制允许生产者将多个发送消息的操作作为一个原子操作进行处理。使用事务机制可以确保消息在发送的过程中要么全部发送成功要么全部发送失败保障消息在传输过程中的一致性。需要注意的是事务机制会影响性能因为在事务提交前消息会暂时存储在内存中直到事务提交后才会发送到 RabbitMQ。消息的确认和重发 RabbitMQ 提供了消息的确认和重发机制当消息被消费者接收后消费者可以通过确认消息的方式通知 RabbitMQ消息已经被处理。如果消息处理失败消费者可以拒绝消息并要求 RabbitMQ 重新投递。通过消息的确认和重发机制可以保障消息在传输过程中的可靠性确保每条消息都被正确处理。镜像队列 镜像队列是指将队列的数据复制到多个节点上实现队列的冗余和高可用性。当一个节点发生故障时其他节点可以继续提供服务。通过使用镜像队列可以增加消息队列的可靠性和一致性。 总结来说为了保障消息在传输过程中的可靠性和一致性可以使用生产者确认机制、持久化、事务机制、消息的确认和重发以及镜像队列等方法。通过合理地使用这些机制可以确保消息在传输过程中的安全和可靠处理。 4.11 小结 本章介绍了 RabbitMQ 的进阶特性包括消息何去何从、过期时间、死信队列、延迟队列、优先级队列、RPC 实现、持久化、生产者确认和消费端要点等功能。在下一章中我们将学习 RabbitMQ 的管理和配置包括多租户与权限、用户管理、Web 端管理、应用与集群管理等内容。
http://www.pierceye.com/news/77192/

相关文章:

  • 广西网站建电子商务平台信息系统建设
  • seo做的不好的网站有哪些南宁建设工程质量网站
  • 电商网站设计公司排行榜空投网站建设
  • 免费建站平台哪个稳定平面设计和网页设计
  • 苏州全网网站建设wordpress站点统计代码
  • wap网站和app开发简述网站开发工作流程
  • 网站开发怎么才能接到私活做微整的网站
  • 八里河风景区网站建设设计概述wordpress主题和模板下载
  • 云主机网站配置宿迁房产网 新楼盘
  • 长春建筑公司有哪些公司seo搜索引擎优化总结报告
  • 做设计找参考的设计网站有那些wordpress建立网盘
  • 网站站点多少钱2345浏览器官网下载
  • 网站愉建设免费申请电子邮箱注册
  • 郴州竞价网站建设方案wordpress国际化
  • 一流高职院校建设计划项目网站建立公司的流程
  • 青岛网站建设工作室移动互联网小程序开发
  • 黄页88网站推广方案vi设计培训公司
  • 网站建设属于什么服务wordpress 优化版
  • 建设公司网站费用代做设计网站
  • 纸 技术支持 东莞网站建设重庆今天最新新闻
  • 公司查名网站成都展示型网页制作公司
  • 镇江网站建设联系思创软文广告怎么写
  • 网站如何建立网站空间1g多少钱
  • 我市建设车辆违章查询网站 病句利用access数据库做网站
  • wordpress 对接酷q新郑做网站优化
  • 网站推广在哪好高德地图可以看国外的地图吗
  • 招聘网站建设流程图网站推广服务合同模板
  • 简历模板简单免费凡科网站可以做seo优化
  • 织梦网站打不开企业名录搜索软件推荐
  • 什么是网站地址淘客帝国 wordpress