RabbitMQ练习(Routing)

news2024/9/22 13:27:25

 1、RabbitMQ教程

《RabbitMQ Tutorials》icon-default.png?t=N7T8https://www.rabbitmq.com/tutorials

2、环境准备

参考:《RabbitMQ练习(Hello World)》和《RabbitMQ练习(Work Queues)》。

确保RabbitMQ、Sender、Receiver、Receiver2容器正常安装和启动。

root@k0test1:~# docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.13-management
root@k0test1:~# docker start sender
root@k0test1:~# docker start receiver
root@k0test1:~# docker start receiver2
root@k0test1:~# docker network inspect bridge

3、Routing练习

3.1 概述

之前练习了一个简单的日志系统,能够将日志消息广播给多个接收者。本练习中,将订阅消息的子集。例如,只将关键的错误消息定向到日志文件,同时在控制台上打印所有日志消息。

3.2 绑定(bindings)

绑定是连接交换机(exchanges)和队列(queues)的规则,它们定义了消息如何从一个交换机路由到一个或多个队列。之前的练习中创建过队列和交换机绑定:

channel.queue_bind(exchange=exchange_name, queue=queue_name)

绑定还可以包含一个额外的 routing_key 参数。为了避免与 basic_publish 参数里的routing_key混淆,我们将它称为binding key。以下是创建带有绑定键的绑定的方法:

channel.queue_bind(exchange=exchange_name, queue=queue_name, routing_key='black')

binding key的含义取决于exchange的类型。之前使用的fanout exchange会忽略binding key

3.3 Direct exchange

之前的简单日志系统练习中,将所有消息广播给所有消费者。本练习中将根据消息的严重程度来过滤消息。例如,只将"critical errors"日志消息写入磁盘,“warning or info”日志消息不写入磁盘,从而节约磁盘空间。

fanout exchange只能进行无差别的广播,缺少灵活性。

本练习将使用direct exchange。direct exchange背后的路由算法很简单——消息会发送到其绑定键与消息的路由键完全匹配的队列(划重点!!)

以下为举例说明:

上图中direct exchange 有两个队列绑定到它上面。第一个队列有一个绑定,绑定键是 orange,第二个队列有两个绑定,一个绑定键是 black,另一个是 green

在这样一个设置中,一个带有路由键 orange 发布到交换机的消息将会被路由到队列 Q1。带有路由键 black 或 green 的消息将会发送到队列 Q2。所有其他消息将会被丢弃。

3.4 Multiple bindings

相同的绑定键完全可以同时绑定多个队列。比如在 direct exchange和 Q1 之间添加一个带有绑定键 black 的绑定。在这种情况下,direct exchange 将和fanout exchange一样,将消息广播到所有匹配的队列,带有路由键 black 的消息将被传递到 Q1 和 Q2。

3.5 代码说明

3.5.1 Sending

进入sender容器,vi编写emit_log_direct.py:

root@sender:/# vi emit_log_direct.py
root@sender:/# cat emit_log_direct.py 
import pika
import sys

connection = pika.BlockingConnection(
    pika.ConnectionParameters(host='172.17.0.2'))
channel = connection.channel()

channel.exchange_declare(exchange='direct_logs', exchange_type='direct')

severity = sys.argv[1] if len(sys.argv) > 1 else 'info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'
channel.basic_publish(
    exchange='direct_logs', routing_key=severity, body=message)
print(f" [x] Sent {severity}:{message}")
connection.close()
root@sender:/# 

 这段代码是一个使用 pika 库的 Python 脚本,用于与 RabbitMQ 消息队列进行交互。它演示了如何将消息发布到一个名为 direct_logs 的直接交换机(direct exchange)。下面是对代码的详细说明:

  1. 导入模块

    • import pika:导入 pika 模块,这是一个用于 RabbitMQ 的 Python 客户端库。
    • import sys:导入 sys 模块,用于访问由命令行参数传递的参数。
  2. 建立连接

    • connection = pika.BlockingConnection(pika.ConnectionParameters(host='172.17.0.2')):创建一个连接到 RabbitMQ 服务器,服务器的 IP 地址是 172.17.0.2
  3. 创建通道

    • channel = connection.channel():创建一个新的通道(channel),用于在客户端和消息队列之间发送和接收消息。
  4. 声明交换

    • channel.exchange_declare(exchange='direct_logs', exchange_type='direct'):声明一个名为 direct_logs 的直接交换。直接交换根据消息的路由键(routing key)将消息路由到一个或多个绑定的队列。
  5. 获取命令行参数

    • severity = sys.argv[1] if len(sys.argv) > 1 else 'info':获取第一个命令行参数作为消息的严重性级别(severity),如果没有提供,则默认为 'info'
    • message = ' '.join(sys.argv[2:]) or 'Hello World!':获取第二个及之后的命令行参数,并将其连接成一个字符串作为消息内容,如果没有提供,则默认为 'Hello World!'
  6. 发布消息

    • channel.basic_publish(exchange='direct_logs', routing_key=severity, body=message):使用 basic_publish 方法发布消息到 direct_logs 交换。消息的路由键设置为 severity,消息体设置为 message
  7. 打印确认信息

    • print(f" [x] Sent {severity}:{message}"):打印一条消息,确认消息已经发送,并显示发送的严重性级别和消息内容。
  8. 关闭连接

    • connection.close():关闭与 RabbitMQ 的连接。

这个脚本通常作为消息生产者使用,它将消息发送到消息队列中,然后由消费者根据路由键从相应的队列中接收并处理这些消息。

3.5.2 Receiving

进入receiver/receiver2容器,vi编写receive_logs_direct.py:

root@receiver:/# vi receive_logs_direct.py
root@receiver:/# cat receive_logs_direct.py 
import pika
import sys

connection = pika.BlockingConnection(
    pika.ConnectionParameters(host='172.17.0.2'))
channel = connection.channel()

channel.exchange_declare(exchange='direct_logs', exchange_type='direct')

result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue

severities = sys.argv[1:]
if not severities:
    sys.stderr.write("Usage: %s [info] [warning] [error]\n" % sys.argv[0])
    sys.exit(1)

for severity in severities:
    channel.queue_bind(
        exchange='direct_logs', queue=queue_name, routing_key=severity)

print(' [*] Waiting for logs. To exit press CTRL+C')


def callback(ch, method, properties, body):
    print(f" [x] {method.routing_key}:{body}")


channel.basic_consume(
    queue=queue_name, on_message_callback=callback, auto_ack=True)

channel.start_consuming()
root@receiver:/# 

这段代码是一个 Python 脚本,使用 pika 库来与 RabbitMQ 消息队列进行交互。它演示了如何创建一个消费者,该消费者订阅了具有不同严重性级别的日志消息。下面是对代码的详细说明:

  1. 导入模块

    • import pika:导入 pika 模块,这是用于 RabbitMQ 的 Python 客户端库。
    • import sys:导入 sys 模块,用于访问命令行参数。
  2. 建立连接

    • connection = pika.BlockingConnection(pika.ConnectionParameters(host='172.17.0.2')):创建一个连接到 RabbitMQ 服务器,服务器的 IP 地址是 172.17.0.2
  3. 创建通道

    • channel = connection.channel():创建一个新的通道,用于在客户端和消息队列之间发送和接收消息。
  4. 声明交换

    • channel.exchange_declare(exchange='direct_logs', exchange_type='direct'):声明一个名为 direct_logs 的直接交换,用于根据消息的路由键将消息路由到队列。
  5. 声明队列

    • result = channel.queue_declare(queue='', exclusive=True):声明一个非持久的、独占的队列。exclusive=True 意味着这个队列只对连接它的用户可用,并且在连接关闭时队列将被删除。
    • queue_name = result.method.queue:从声明的结果中获取队列名称。
  6. 获取命令行参数作为严重性级别

    • severities = sys.argv[1:]:获取所有命令行参数(除了脚本名称),这些参数代表不同的日志严重性级别。
    • if not severities::如果没有提供严重性级别,打印用法信息并退出程序。
  7. 绑定队列到交换

    • for severity in severities::遍历所有提供的严重性级别。
    • channel.queue_bind(...):为每个严重性级别创建一个绑定,将队列绑定到 direct_logs 交换,使用相应的严重性级别作为路由键。
  8. 等待日志消息

    • print(' [*] Waiting for logs. To exit press CTRL+C'):打印一条消息,告知用户程序正在等待日志消息,并说明如何退出程序。
  9. 定义回调函数

    • def callback(ch, method, properties, body)::定义一个回调函数,当消息到达时会被调用。
    • print(f" [x] {method.routing_key}:{body}"):在控制台打印出消息的路由键和消息体。
  10. 设置消息消费

    • channel.basic_consume(...):设置消息消费,指定队列名称、回调函数和自动确认消息。
    • auto_ack=True:设置为自动确认消息,一旦消息被传递给回调函数,RabbitMQ 就会认为消息已被处理。
  11. 开始消费

    • channel.start_consuming():启动消息消费过程,直到程序被外部中断(如用户按下 CTRL+C)。

这个脚本通常作为消息消费者使用,它订阅了具有特定严重性级别的日志消息,并将这些消息打印到控制台。通过命令行参数指定感兴趣的日志级别,可以灵活地选择接收哪些类型的日志消息。

3.6 开始测试

1、保存特定级别日志到文件

  • 进入receiver容器
  • 执行以下命令以仅保存'warning'和'error'级别的日志到文件logs_from_rabbit.log
root@receiver:/# python3 receive_logs_direct.py warning error > logs_from_rabbit.log

2. 在屏幕上显示所有日志消息

  • 进入receiver2容器
  • 执行以下命令以在屏幕上显示所有级别的日志消息:
root@receiver2:/# python3 receive_logs_direct.py info warning error
 [*] Waiting for logs. To exit press CTRL+C

3、在rabbitmq容器上查看队列绑定信息

root@48a7ed758af4:/# rabbitmqctl list_bindings
Listing bindings for vhost /...
source_name     source_kind     destination_name        destination_kind        routing_key     arguments
        exchange        amq.gen-_ZUcAq9DRQigdae9-eBtCQ  queue   amq.gen-_ZUcAq9DRQigdae9-eBtCQ  []
        exchange        amq.gen-xNR7HxvupGNgQN0pdDdZ_w  queue   amq.gen-xNR7HxvupGNgQN0pdDdZ_w  []
direct_logs     exchange        amq.gen-_ZUcAq9DRQigdae9-eBtCQ  queue   error   []
direct_logs     exchange        amq.gen-xNR7HxvupGNgQN0pdDdZ_w  queue   error   []
direct_logs     exchange        amq.gen-xNR7HxvupGNgQN0pdDdZ_w  queue   info    []
direct_logs     exchange        amq.gen-_ZUcAq9DRQigdae9-eBtCQ  queue   warning []
direct_logs     exchange        amq.gen-xNR7HxvupGNgQN0pdDdZ_w  queue   warning []
root@48a7ed758af4:/# 

4. 发送错误日志消息

  • 进入sender容器。
  • 执行以下命令以发送一条错误级别的日志消息:
root@sender:/# python3 emit_log_direct.py error "Run. Run. Or it will explode."
 [x] Sent error:Run. Run. Or it will explode.
root@sender:/# python3 emit_log_direct.py info "This is info log"
 [x] Sent info:This is info log
root@sender:/# python3 emit_log_direct.py warning "This is warning log"
 [x] Sent warning:This is warning log
root@sender:/# 
  • 观察发送命令的终端,确认输出显示消息已发送。 

5. 验证日志接收

  • 查看receiver容器,验证文件logs_from_rabbit.log是否已创建,并且只包含'warning'和'error'级别的日志条目。
root@receiver:/# cat logs_from_rabbit.log 
 [*] Waiting for logs. To exit press CTRL+C
 [x] error:b'Run. Run. Or it will explode.'
 [x] warning:b'This is warning log'
root@receiver:/# 
  • 查看receiver2容器,检查是否接收到了步骤3中发送的错误日志消息,并显示在屏幕上。
root@receiver2:/# python3 receive_logs_direct.py info warning error
 [*] Waiting for logs. To exit press CTRL+C
 [x] error:b'Run. Run. Or it will explode.'
 [x] info:b'This is info log'
 [x] warning:b'This is warning log'

4、Wireshark抓包

4.1 抓包方式

参考:《RabbitMQ练习(Hello World)》

4.2 抓包信息

4.2.1 消费者开始接收消息

 典型数据包:

1、bindings —— Frame 20

Packet comments
Frame 20: 136 bytes on wire (1088 bits), 136 bytes captured (1088 bits) on interface docker0, id 0
Ethernet II, Src: 02:42:ac:11:00:04 (02:42:ac:11:00:04), Dst: 02:42:ac:11:00:02 (02:42:ac:11:00:02)
Internet Protocol Version 4, Src: 172.17.0.4 (172.17.0.4), Dst: 172.17.0.2 (172.17.0.2)
Transmission Control Protocol, Src Port: 34112, Dst Port: 5672, Seq: 415, Ack: 634, Len: 70
Advanced Message Queuing Protocol
    Type: Method (1)
    Channel: 1
    Length: 62
    Class: Queue (50)
    Method: Bind (20)
    Arguments
        Ticket: 0
        Queue: amq.gen-b1hFBxHkj-Ee4gbS3ZmIZw
        Exchange: direct_logs
        Routing-Key: warning
        .... ...0 = Nowait: False
        Arguments

这段文本描述的是一个 AMQP (Advanced Message Queuing Protocol) 协议的帧,具体是关于队列绑定的一个方法调用。以下是对这段文本的详细解读:

  1. AMQP 类型:

    • Type: Method (1): 这表明帧是一个方法调用,用于执行AMQP协议中定义的操作。
  2. 通道号:

    • Channel: 1: 这个帧在AMQP的会话中的通道号是1。
  3. 长度:

    • Length: 62: 帧的总长度是62字节,包括方法帧头和参数。
  4. AMQP 类:

    • Class: Queue (50): 这表明帧属于队列类,队列类用于处理队列相关的操作。
  5. 方法:

    • Method: Bind (20): 这是bind方法,用于将队列绑定到一个交换机上,这样交换机就可以将消息路由到这个队列。
  6. 参数:

    • Ticket: 0: 访问权限的票据,0通常表示使用默认的票据。
    • Queue: amq.gen-b1hFBxHkj-Ee4gbS3ZmIZw: 要绑定的队列名称。
    • Exchange: direct_logs: 队列要绑定到的交换机名称。
    • Routing-Key: warning: 路由键(绑定键),用于指定当消息发送到交换机时,如何根据这个键将消息路由到队列。在这个例子中,路由键是warning,意味着只有带有warning路由键的消息会被路由到这个队列。
  7. 选项标志:

    • Nowait: False: 表示客户端期望服务器对这个请求做出响应。如果设置为True,则客户端不期望响应。
  8. 其他参数:

    • Arguments: 这通常包含额外的参数,但在这段文本中没有提供具体的参数值。

这个bind方法调用的目的是将一个队列绑定到一个直接交换机上,并且指定了路由键为warning。这意味着任何发送到direct_logs交换机并带有warning路由键的消息都会被路由到amq.gen-b1hFBxHkj-Ee4gbS3ZmIZw队列。这是一种常见的消息路由机制,用于确保消息根据特定的业务逻辑或条件被正确地分发到不同的队列。

2、开始接收消息 —— Frame 24 

Frame 24: 155 bytes on wire (1240 bits), 155 bytes captured (1240 bits) on interface docker0, id 0
Ethernet II, Src: 02:42:ac:11:00:04 (02:42:ac:11:00:04), Dst: 02:42:ac:11:00:02 (02:42:ac:11:00:02)
Internet Protocol Version 4, Src: 172.17.0.4 (172.17.0.4), Dst: 172.17.0.2 (172.17.0.2)
Transmission Control Protocol, Src Port: 34112, Dst Port: 5672, Seq: 553, Ack: 658, Len: 89
Advanced Message Queuing Protocol
    Type: Method (1)
    Channel: 1
    Length: 81
    Class: Basic (60)
    Method: Consume (20)
    Arguments
        Ticket: 0
        Queue: amq.gen-b1hFBxHkj-Ee4gbS3ZmIZw
        Consumer-Tag: ctag1.711eb50abcc64a798dbf5d6ae61cb296
        .... ...0 = No-Local: False
        .... ..1. = No-Ack: True
        .... .0.. = Exclusive: False
        .... 0... = Nowait: False
        Filter

这段文本描述的是一个 AMQP (Advanced Message Queuing Protocol) 协议的帧,具体是关于消息消费请求的一个方法调用。以下是对这段文本的详细解读:

  1. AMQP 类型:

    • Type: Method (1): 这表明帧是一个方法调用,用于执行AMQP协议中定义的操作。
  2. 通道号:

    • Channel: 1: 这个帧在AMQP会话中的通道号是1。
  3. 长度:

    • Length: 81: 帧的总长度是81字节,包括方法帧头和参数。
  4. AMQP 类:

    • Class: Basic (60): 这表明帧属于基础类,基础类用于处理消息的发布和订阅。
  5. 方法:

    • Method: Consume (20): 这是consume方法,用于建立消费者,以便从队列中接收消息。
  6. 参数:

    • Ticket: 0: 访问权限的票据,0通常表示使用默认的票据。
    • Queue: amq.gen-b1hFBxHkj-Ee4gbS3ZmIZw: 消费者要订阅的队列名称。
    • Consumer-Tag: ctag1.711eb50abcc64a798dbf5d6ae61cb296: 消费者的唯一标识符。
  7. 选项标志:

    • No-Local: False: 表示消费者可以接收到发送者自己发送的消息。
    • No-Ack: True: 表示消费者接收到消息后不需要发送确认。这通常用于性能优化,但需要注意,如果消费者异常终止,未确认的消息可能会丢失。
    • Exclusive: False: 表示队列可以被多个消费者共享。
    • Nowait: False: 表示客户端期望服务器对这个请求做出响应。如果设置为True,则客户端不期望响应。
  8. Filter:

    • 这个参数可能表示一个消息筛选器,用于决定哪些消息应该被消费者接收。然而,这段文本中的Filter后面没有提供具体的参数值,可能是信息被截断了。

这个consume方法调用的目的是让消费者订阅一个队列,并开始接收消息。由于No-Ack被设置为True,消费者在接收到消息后不需要发送回执,这可以提高消息处理的吞吐量,但牺牲了消息的可靠性保证。如果对消息的可靠性有要求,应该将No-Ack设置为False,这样消费者在处理完每条消息后都需要发送一个确认回执给服务器。

4.2.2 生产者发送消息 

典型数据包:

1、消息发布到交换机 —— Frame 83

Frame 83: 99 bytes on wire (792 bits), 99 bytes captured (792 bits) on interface docker0, id 0
Ethernet II, Src: 02:42:ac:11:00:03 (02:42:ac:11:00:03), Dst: 02:42:ac:11:00:02 (02:42:ac:11:00:02)
Internet Protocol Version 4, Src: 172.17.0.3 (172.17.0.3), Dst: 172.17.0.2 (172.17.0.2)
Transmission Control Protocol, Src Port: 46386, Dst Port: 5672, Seq: 395, Ack: 583, Len: 33
Advanced Message Queuing Protocol
    Type: Method (1)
    Channel: 1
    Length: 25
    Class: Basic (60)
    Method: Publish (40)
    Arguments
        Ticket: 0
        Exchange: direct_logs
        Routing-Key: error
        .... ...0 = Mandatory: False
        .... ..0. = Immediate: False

这段文本描述的是一个 AMQP (Advanced Message Queuing Protocol) 协议的帧,具体是关于消息发布请求的一个方法调用。以下是对这段文本的详细解读:

  1. AMQP 类型:

    • Type: Method (1): 这表明帧是一个方法调用,用于执行AMQP协议中定义的操作。
  2. 通道号:

    • Channel: 1: 这个帧在AMQP会话中的通道号是1。
  3. 长度:

    • Length: 25: 帧的总长度是25字节,包括方法帧头和参数。
  4. AMQP 类:

    • Class: Basic (60): 这表明帧属于基础类,基础类用于处理消息的发布和订阅。
  5. 方法:

    • Method: Publish (40): 这是publish方法,用于将消息发布到一个交换机。
  6. 参数:

    • Ticket: 0: 访问权限的票据,0通常表示使用默认的票据。
    • Exchange: direct_logs: 消息要发布的交换机名称。在这个例子中,交换机的类型是直接交换机(direct exchange),它根据路由键将消息路由到一个或多个队列。
    • Routing-Key: error: 路由键,用于指定消息的路由。在这个例子中,路由键是error,意味着消息将被路由到绑定了error路由键的队列。
  7. 选项标志:

    • Mandatory: False: 表示如果消息不能被路由到任何队列,服务器不会返回一个否定的确认(通常是一个返回码)。如果设置为True,则在没有队列绑定到指定的路由键时,服务器会返回一个否定的确认。
    • Immediate: False: 表示消息应该被路由到队列,即使没有消费者正在监听。如果设置为True,则只有当队列上至少有一个活跃的消费者时,消息才会被投递。

这个publish方法调用的目的是将消息发布到direct_logs交换机,并指定路由键为error。消息将根据这个路由键被路由到一个或多个绑定了相应路由键的队列。由于MandatoryImmediate都被设置为False,这表明发布者对消息的路由和队列上是否有消费者不作特别要求。

 2、发送的具体消息 —— Frame 85

Frame 85: 103 bytes on wire (824 bits), 103 bytes captured (824 bits) on interface docker0, id 0
Ethernet II, Src: 02:42:ac:11:00:03 (02:42:ac:11:00:03), Dst: 02:42:ac:11:00:02 (02:42:ac:11:00:02)
Internet Protocol Version 4, Src: 172.17.0.3 (172.17.0.3), Dst: 172.17.0.2 (172.17.0.2)
Transmission Control Protocol, Src Port: 46386, Dst Port: 5672, Seq: 450, Ack: 583, Len: 37
Advanced Message Queuing Protocol
    Type: Content body (3)
    Channel: 1
    Length: 29
    Payload: 52756e2e2052756e2e204f722069742077696c6c206578706c6f64652e

 这段文本描述的是 AMQP (Advanced Message Queuing Protocol) 协议中的一个内容体帧(Content body frame)。以下是对这段文本的详细解读:

  1. AMQP 类型:

    • Type: Content body (3): 这表明帧是消息内容体的一部分,用于传输消息的实际数据。
  2. 通道号:

    • Channel: 1: 这个帧使用的是通道号1,与之前的Method帧相同,表示这是同一会话的一部分。
  3. 长度:

    • Length: 29: 帧的总长度是29字节,包括帧头和有效载荷。
  4. 有效载荷(Payload):

    • Payload: 52756e2e2052756e2e204f722069742077696c6c206578706c6f64652e: 这是消息内容的二进制表示,通常以十六进制格式显示。在这个例子中,它看起来像是一个字符串,但以十六进制编码。

内容体帧是AMQP协议中消息发布机制的一部分。当客户端使用 Publish 方法将消息发送到交换机时,消息内容会通过一个或多个内容体帧进行传输。这些帧会按照顺序发送,并且在接收端重新组装成完整的消息。

在这个例子中,消息内容是一个警告或指示性的文本,可能是一个日志消息或某种形式的状态更新。消息通过AMQP协议的通道1发送,并且由于使用了内容体帧,它可能是一个多帧消息的一部分。如果消息较长,它可能会分布在多个内容体帧中。

4.2.3 RabbitMQ 向消费者发送消息

Frame 87: 203 bytes on wire (1624 bits), 203 bytes captured (1624 bits) on interface docker0, id 0
Ethernet II, Src: 02:42:ac:11:00:02 (02:42:ac:11:00:02), Dst: 02:42:ac:11:00:05 (02:42:ac:11:00:05)
Internet Protocol Version 4, Src: 172.17.0.2 (172.17.0.2), Dst: 172.17.0.5 (172.17.0.5)
Transmission Control Protocol, Src Port: 5672, Dst Port: 38582, Seq: 721, Ack: 709, Len: 137
Advanced Message Queuing Protocol
    Type: Method (1)
    Channel: 1
    Length: 70
    Class: Basic (60)
    Method: Deliver (60)
    Arguments
        Consumer-Tag: ctag1.da86a92a85bc4dc48ea8bb0bbb143580
        Delivery-Tag: 1
        .... ...0 = Redelivered: False
        Exchange: direct_logs
        Routing-Key: error
Advanced Message Queuing Protocol
    Type: Content header (2)
    Channel: 1
    Length: 14
    Class ID: Basic (60)
    Weight: 0
    Body size: 29
    Property flags: 0x0000
    Properties
Advanced Message Queuing Protocol
    Type: Content body (3)
    Channel: 1
    Length: 29
    Payload: 52756e2e2052756e2e204f722069742077696c6c206578706c6f64652e

 这段文本描述了通过 AMQP 协议传输的一系列消息帧,具体包括方法帧、内容头帧和内容体帧。以下是对这些帧的详细解读:

  1. AMQP Method Frame:

    • Type: Method (1): 表示这是一个方法帧,用于执行AMQP协议中定义的操作。
    • Channel: 1: 帧使用的通道号为1。
    • Length: 70: 方法帧的总长度为70字节。
    • Class: Basic (60): 属于AMQP的基础类,用于消息的发布和订阅。
    • Method: Deliver (60): 这是一个deliver方法,用于将消息传递给消费者。
  2. Deliver Method Arguments:

    • Consumer-Tag: ctag1.da86a92a85bc4dc48ea8bb0bbb143580: 消费者的唯一标识符。
    • Delivery-Tag: 1: 消息的唯一标识符,通常是一个序列号。
    • Redelivered: False: 表示这条消息不是重新投递的。
    • Exchange: direct_logs: 消息通过的交换机名称。
    • Routing-Key: error: 消息的路由键,用于将消息路由到正确的队列。
  3. AMQP Content Header Frame:

    • Type: Content header (2): 表示这是一个内容头帧,包含了消息的元数据。
    • Channel: 1: 使用的通道号为1。
    • Length: 14: 内容头帧的长度为14字节。
    • Class ID: Basic (60): 消息的类别ID,这里是基础类。
    • Weight: 0: 消息的优先级权重,这里设置为0。
    • Body size: 29: 消息体的大小为29字节。
    • Property flags: 0x0000: 属性标志,这里没有设置任何属性。
  4. AMQP Content Body Frame:

    • Type: Content body (3): 表示这是一个内容体帧,包含了消息的实际数据。
    • Channel: 1: 使用的通道号为1。
    • Length: 29: 内容体帧的长度为29字节。
    • Payload: 52756e2e2052756e2e204f722069742077696c6c206578706c6f64652e: 消息内容的二进制数据,以十六进制表示。
  5. 消息内容解码:

    • 将十六进制的Payload解码为字符串,我们得到:"Run. Run. Or it will explode." 这是消息的实际内容,看起来像是一个警告或指示性的消息。

总结来说,这些帧表示通过AMQP协议发送给了一个消费者(由Consumer-Tag标识)一条消息,这条消息最初是发布到direct_logs交换机上,并使用error路由键路由。消息的内容是一个文本字符串,被编码并包含在内容体帧中。

 4.3 只显示消息发送过程的抓包信息

4.4 只显示消息发送过程的抓包流量图 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2085076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能训练师一级(高级技师)、二级(技师)考试指南

随着经济快速发展,人工智能技术在制造业、交通运输、农业、医疗健康、金融服务、物流配送以及城市服务等多个领域得到了广泛的应用。不仅带来产业的转型升级,更是对具备相应技能的人工智能训练师需求的激增。 根据教育部发布的《关于做好职业教育“…

BugKu练习记录:把猪困在猪圈里

题目: 用base64解码 再对应猪圈密码解码,得到答案 t h i s i s p i g p a s s w o r d

house of pig

文章目录 house of pig介绍:利用条件:利用流程: 例题:利用: 总结: house of pig 介绍: House of Pig 是一个将 Tcache Stash Unlink Attack 和 FSOP 结合的攻击,同时使用到了 Larg…

MQ专题:事务消息的实现方式

方案 事务消息投递的过程 step1:开启本地事务step2:执行本地业务step3:消息表t_msg写入记录,status为0(待投递到MQ)step4:提交本地事务step5:若事务提交成功,则投递消息…

【原创教程】电气电工13:按钮开关指示灯篇

按钮开关在电气电工工作中,看似简单,但是有些细节问题,我们还是要注意的。电气电工工作是一个完整的体系,任何一件事疏忽,都会埋下安全隐患。 首先我们来看下 开关按钮的定义: 按钮开关是指利用按钮推动传动机构,使动触点与静触点按通或断开并实现电路换接的开关。按…

软件测试面试题!收藏起来,每天看一看,月薪20K!

初级测试总结题!必背!必背!必背! 1)软件的概念? 软件是计算机系统中与硬件相互依存的一部分,包括程序、数据以及与其相关文档的完整集合。 2)软件测试的概念? 使用人…

讲透一个强大的算法模型,Transformer

Transformer 模型是一种基于注意力机制的深度学习模型,广泛应用于自然语言处理(NLP)任务,如机器翻译、文本生成和语义理解。 它最初由 Vaswani 等人在2017年的论文《Attention is All You Need》中提出。它突破了传统序列模型&am…

搬运5款实用工具,帮你更好地完成各种任务

​ 在日常工作和生活中,使用各种工具来提升效率和简化任务变得尤为重要。本文将介绍几款实用的工具,帮助你更好地完成各种任务。 1. 自动化脚本——AutoHotkey ​ AutoHotkey是一款功能强大的自动化脚本编写工具,可以用来自动执行日常任务&…

【网络安全】漏洞挖掘

漏洞描述 Spring框架为现代基于java的企业应用程序(在任何类型的部署平台上)提供了一个全面的编程和配置模型。 Spring Cloud 中的 serveless框架 Spring Cloud Function 中的 RoutingFunction 类的 apply 方法将请求头中的“spring.cloud.function.routing-expression”参数…

餐饮_零售_麻辣烫_水果店_零食店_生鲜店等收银系统

介绍 多商户多门店的Sass收银系统。适用于餐饮_零售_麻辣烫_水果店_零食店_生鲜店等收银系统,包含windows收银pos端、商家小程序管理端、商家运营端、电子会员、电子小票 软件架构 收银Pos:vue2、node、electron、sqlite、antd 后端服务:spri…

【如何用本机的Navicat远程连接到ubuntu服务器上的mysql】

文章目录 版本一、ubuntu服务器安装mysql5二、远程连接——mysql配置1.创建新mysql用户2.修改配置文件3.查看端口是否开启 三、远程连接——Navicat 版本 mysql:5.7.32 服务器:ubuntu20.04 PC:win10 一、ubuntu服务器安装mysql5 因为ubuntu20.04默认mysql其实是my…

Windows超好用的命令行工具--Cmder 赶紧把cmd丢了吧!

简介 Cmder 是一个现代化的命令行工具可以智能提示,高亮显示文件夹… 1. 官网地址:Cmder下载地址 2. 滑倒最下面可以看到以下按钮 3. 解压到自己想要保存的地址(⚠️记住这个路径) 比如我解压到了C:\Cmder\Cmder.exe(⚠️不推…

变天了!24岁硕士年薪50万元,博士年薪200万起!人才缺口100万

从上海交大硕士毕业的00后表示,“24岁硕士毕业时年薪50万元,到了30岁大概能升到P7(注:职级名称),那时就能年薪百万了。” 他今年入职腾讯,担任AI算法工程师,成为AI风口下第一批就业的年轻人。 …

CUDA 内核函数

文章目录 一、简介二、实现代码三、实现效果参考资料 一、简介 CUDA为我们提供了可扩展的编程模型:它的核心是三个关键的抽象——线程组的层次结构、共享内存和阻塞同步——它们只是作为一组最小的语言扩展暴露给外部使用人员。这些抽象提供细粒度数据并行性和线程并…

MyBatis的学习————上篇

目录 一、MyBatis简介 1、MyBatis的历史 2、MyBatis的特性 3、和其它持久化层技术的比较 二、搭建MyBatis 1、开发环境 ​编辑2、创建Maven工程 3、创建MyBatis核心配置文件 4、创建mapper接口 5、创建Mybatis的映射文件 6、测试功能 7、功能优化 8、修改和删除方…

重生奇迹MU最合适PK的几个职业

重生奇迹MU是一款备受玩家青睐的经典游戏,其中的PK系统更是吸引了众多玩家的关注。在众多职业中,哪些职业最适合PK呢? PK作为重生奇迹MU的一种娱乐方式,已成为该游戏核心系统之一,并在多年的流行中仍能带给玩家许多乐…

python正则表达式的一些问题

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收…

Matplotlib中twinx() 函数的用法

ax1.twinx() 是 Matplotlib 库中的一个函数,用于在同一个图中创建一个共享 x 轴但具有独立 y 轴的双 y 轴图表。这个函数非常适合用来在同一张图中绘制两组具有不同 y 轴度量的变量,使得它们可以共享 x 轴,但彼此之间有不同的 y 轴尺度。 ax…

SpringBoot日常:Spring扩展接口之InitializingBean

文章目录 简介源码分析应用场景代码示例运行示例 简介 这篇文章主要介绍了Spring中InitializingBean的使用详细解析,InitializingBean是Spring提供的拓展性接口,提供了属性初始化后的处理方法,它只有一个afterPropertiesSet方法,凡是继承该接…

中断的引入

中断系统是为使CPU具有对外界紧总事件的实时处理能力而设置的 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原…