当前位置:首页>python>Python 中间件系列:消息队列 RabbitMQ 操作

Python 中间件系列:消息队列 RabbitMQ 操作

  • 2026-06-30 08:38:44
Python 中间件系列:消息队列 RabbitMQ 操作
  在现代分布式系统中,消息队列如同人体的神经系统,负责在各个服务之间可靠、高效地传递信息。RabbitMQ 作为 AMQP(高级消息队列协议)的标杆实现,凭借其灵活的路由、可靠的消息投递和丰富的生态,成为了架构师工具箱中的必备品。本文作为 

Python 中间件系列 的开篇,将带你从零开始,用 Python 操作 RabbitMQ,从 “Hello World” 直连模式讲到延迟队列、RPC 等高级场景,所有示例均附带可直接运行的代码和详尽的控制台输出解析。

目录

  1. 核心概念速览
  2. 环境准备
  3. 第一章:Hello World —— 最简单的消息模型
  4. 第二章:工作队列 —— 任务的分发与负载均衡
  5. 第三章:发布/订阅 —— 用 Fanout 交换机广播消息
  6. 第四章:路由模式 —— 用 Direct 交换机精准投递
  7. 第五章:主题模式 —— 用 Topic 交换机实现灵活匹配
  8. 第六章:消息可靠性 —— 确认、持久化与发布者确认
  9. 第七章:高级应用 —— 死信队列与延迟队列
  10. 第八章:RPC —— 远程过程调用
  11. 结语与最佳实践

1. 核心概念速览

在敲代码之前,先在大脑中建立一张地图。RabbitMQ 的核心由三个角色和两个关键组件构成:

  • 生产者 (Producer)
    :发送消息的应用程序。
  • 消费者 (Consumer)
    :接收并处理消息的应用程序。
  • 队列 (Queue)
    :RabbitMQ 内部的缓冲区,用于存储消息。消息一旦进入队列,就由 RabbitMQ 负责保管,直到消费者取走。
  • 交换机 (Exchange)
    :生产者不会直接把消息发到队列,而是发给交换机。交换机根据规则,决定消息路由到一个或多个队列。主要有四种类型:direct、fanout、topic、headers。
  • 绑定 (Binding)
    :队列和交换机之间的“连线”,在绑定时会指定路由键 (Routing Key)。交换机根据路由键和自身类型,决定把消息投递到哪些绑定的队列。

一句话总结:生产者 -> 交换机 -(通过绑定和路由键)-> 队列 <- 消费者

理解了这张图,后面的代码就只是把它翻译成 Python 语言而已。

2. 环境准备

我们使用 Docker 快速启动 RabbitMQ,并安装 Python 客户端 pika。

启动 RabbitMQ(带管理界面的版本):

dockerrun-d--namerabbitmq-p 5672:5672-p 15672:15672rabbitmq:3-management

启动后,可通过 http://localhost:15672 访问管理界面,默认账号密码 guest/guest。

安装 pika 库:

接下来,所有代码示例都将围绕这两个环境展开。

3. 第一章:Hello World —— 最简单的消息模型

我们先从一个最简单的 单生产者 -> 单消费者 模型开始,发送一句 “Hello World”。

生产者 send.py

import pika# 1. 建立连接connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()# 2. 声明队列(如果队列不存在则创建,存在则复用)channel.queue_declare(queue='hello')# 3. 发布消息channel.basic_publish(exchange='',      # 使用默认交换机                      routing_key='hello'# 消息直接发到 'hello' 队列                      body='Hello World!')print(" [x] Sent 'Hello World!'")# 4. 关闭连接connection.close()

消费者 receive.py

import pika# 1. 建立连接connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()# 2. 声明队列(幂等操作,确保队列存在)channel.queue_declare(queue='hello')# 3. 定义回调函数defcallback(ch, method, properties, body):    print(f" [x] Received {body.decode()}")# 4. 订阅队列channel.basic_consume(queue='hello',                      auto_ack=True,  # 自动确认(先这样,后面会讲)                      on_message_callback=callback)print(' [*] Waiting for messages. To exit press CTRL+C')channel.start_consuming()

运行与输出解析

打开两个终端:

终端 1(消费者):

$ python receive.py [*] Waiting for messages. To exit press CTRL+C [x] Received Hello World!

终端 2(生产者):

$ python send.py [x] Sent 'Hello World!'

这里的关键点:

  • 生产者使用默认交换机(空字符串 ''),此时 routing_key 就是目标队列名。
  • 消费者用 basic_consume 持续监听队列,auto_ack=True 表示消息一旦送出就自动确认删除。

4. 第二章:工作队列 —— 任务的分发与负载均衡

真实世界中,单个消费者往往忙不过来。工作队列允许多个消费者从同一个队列中取任务,消息只被一个消费者处理

循环分发(Round-robin)

默认情况下,RabbitMQ 会把消息轮流发给所有消费者。我们创建持续发送任务的 new_task.py 和多个 worker.py。

生产者 new_task.py:

import pikaimport timeconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.queue_declare(queue='task_queue')for i in range(16):    message = f"Task {i}"    channel.basic_publish(exchange='', routing_key='task_queue', body=message)print(f" [x] Sent '{message}'")    time.sleep(0.5)connection.close()

消费者 worker.py:

import pikaimport timeconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.queue_declare(queue='task_queue')defcallback(ch, method, properties, body):    print(f" [x] Received {body.decode()}")# 模拟处理耗时(偶数任务耗时短,奇数耗时长)    time.sleep(2if int(body.decode().split()[1]) % 2 != 0else0.5)    print(f" [x] Done {body.decode()}")    ch.basic_ack(delivery_tag=method.delivery_tag) # 手动确认# 重要:每次只分发一条消息,消费者处理完并确认后才发下一条channel.basic_qos(prefetch_count=1)channel.basic_consume(queue='task_queue', on_message_callback=callback)print(' [*] Waiting for messages...')channel.start_consuming()

运行与公平分发演示

打开三个终端:一个生产,两个消费。

终端 1(Worker A):

$ python worker.py [*] Waiting for messages... [x] Received Task 1# 耗时2秒 [x] Done Task 1 [x] Received Task 3# 耗时2秒 [x] Done Task 3 [x] Received Task 5# 耗时2秒

终端 2(Worker B):

$ python worker.py [*] Waiting for messages... [x] Received Task 2# 耗时0.5秒,先完成 [x] Done Task 2 [x] Received Task 4# 耗时0.5秒 [x] Done Task 4

终端 3(生产者):

$ python new_task.py [x] Sent 'Task 1' [x] Sent 'Task 2' [x] Sent 'Task 3' [x] Sent 'Task 4' [x] Sent 'Task 5'

输出解读:

  • 我们没有使用自动确认 auto_ack,而是手动 basic_ack。这保证了如果 Worker A 在处理 Task 1 时崩溃,该消息会重新入队并分发给 Worker B。
  • basic_qos(prefetch_count=1) 是关键。它告诉 RabbitMQ:不要同时给我超过 1 条消息。这样 Worker A 在处理 Task 1 时,尽管 Task 2、3 已经入队,但 Task 3 不会预发给 A,而是会发给空闲的 Worker B。这就实现了公平分发,处理速度快的消费者将拿到更多任务。

5. 第三章:发布/订阅 —— 用 Fanout 交换机广播消息

现在,我们需要让多个消费者都能收到同一条消息,就像日志广播。这需要引入交换机。fanout 交换机将消息广播到所有绑定的队列

生产者 emit_log.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()# 声明 fanout 交换机channel.exchange_declare(exchange='logs', exchange_type='fanout')message = "info: Hello Fanout!"channel.basic_publish(exchange='logs', routing_key='', body=message)print(f" [x] Sent {message}")connection.close()

消费者 receive_logs.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.exchange_declare(exchange='logs', exchange_type='fanout')# 让 RabbitMQ 生成一个唯一的、临时队列,消费者断开后自动删除result = channel.queue_declare(queue='', exclusive=True)queue_name = result.method.queue# 绑定队列到交换机channel.queue_bind(exchange='logs', queue=queue_name)print(f' [*] Waiting for logs on queue: {queue_name}')defcallback(ch, method, properties, body):    print(f" [x] {body.decode()}")channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)channel.start_consuming()

运行演示:一发多收

同时启动两个 receive_logs.py,再执行 emit_log.py。

消费者终端 1:

$ python receive_logs.py [*] Waiting for logs on queue: amq.gen-JzTY20BRgKO-HjmUJj0wLg [x] info: Hello Fanout!

消费者终端 2:

$ python receive_logs.py [*] Waiting for logs on queue: amq.gen-0cHw5VhC7KnpjRzAsj0Xww [x] info: Hello Fanout!

生产者终端:

$ python emit_log.py [x] Sent info: Hello Fanout!

可见,两个消费者都收到了相同的消息。关键在于 queue_declare(queue='', exclusive=True):每个消费者启动时都会创建一个随机的独占临时队列,并绑定到 logs 交换机。生产者完全不需要关心消费者的数量和地址,达到了彻底的解耦。

6. 第四章:路由模式 —— 用 Direct 交换机精准投递

Fanout 是“无脑广播”,而 direct 交换机根据完全匹配的路由键,将消息投递给绑定键相同的队列。适用于按日志级别(error、info)分发。

生产者 emit_direct_log.py

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.exchange_declare(exchange='direct_logs', exchange_type='direct')severity = sys.argv[1iflen(sys.argv) > 1else'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()

消费者 receive_direct_log.py

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.exchange_declare(exchange='direct_logs', exchange_type='direct')result = channel.queue_declare(queue='', exclusive=True)queue_name = result.method.queue# 通过命令行参数指定绑定的路由键,如 python receive_direct_log.py error infoseverities = sys.argv[1:] if len(sys.argv) > 1else ['info']for severity in severities:    channel.queue_bind(exchange='direct_logs', queue=queue_name, routing_key=severity)print(f' [*] Waiting for {severities} logs. Queue: {queue_name}')defcallback(ch, method, properties, body):    print(f" [x] {method.routing_key}:{body.decode()}")channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)channel.start_consuming()

运行演示

终端 1(只收 error):

$ python receive_direct_log.py error [*] Waiting for ['error'] logs. Queue: amq.gen-XXX

终端 2(收 error 和 info):

$ python receive_direct_log.py error info [*] Waiting for ['error''info'] logs. Queue: amq.gen-YYY

生产者发送消息:

$ python emit_direct_log.py error "Disk full" [x] Sent error:Disk full$ python emit_direct_log.py info "Server started" [x] Sent info:Server started

输出:终端1只收到 error 消息,终端2则两条都收到。 这种精确匹配非常适合按模块、优先级区分处理。

7. 第五章:主题模式 —— 用 Topic 交换机实现灵活匹配

topic 交换机是 direct 的升级版。路由键是由点分隔的单词列表(如 “weather.us.east”),绑定键可以使用通配符:

  • * 匹配刚好一个单词。
  • # 匹配零个或多个单词。

生产者 emit_topic.py

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.exchange_declare(exchange='topic_logs', exchange_type='topic')routing_key = sys.argv[1iflen(sys.argv) > 1else'anonymous.info'message = ' '.join(sys.argv[2:]) or 'Hello World!'channel.basic_publish(exchange='topic_logs', routing_key=routing_key, body=message)print(f" [x] Sent {routing_key}:{message}")connection.close()

消费者 receive_topic.py

import pikaimport sysconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.exchange_declare(exchange='topic_logs', exchange_type='topic')result = channel.queue_declare('', exclusive=True)queue_name = result.method.queue# 绑定键从命令行接收,例如: "kern.*" 或 "*.critical" 或 "#"binding_keys = sys.argv[1:] if len(sys.argv) > 1else ['anonymous.*']for binding_key in binding_keys:    channel.queue_bind(exchange='topic_logs', queue=queue_name, routing_key=binding_key)print(f' [*] Waiting for logs. Binding keys: {binding_keys}. Queue: {queue_name}')defcallback(ch, method, properties, body):    print(f" [x] {method.routing_key}:{body.decode()}")channel.basic_consume(queue=queue_name, on_message_callback=callback, auto_ack=True)channel.start_consuming()

运行演示

消费者 1:订阅所有 kern 开头的日志

$ python receive_topic.py "kern.*" [*] Waiting for logs. Binding: ['kern.*']

消费者 2:订阅所有 critical 结尾的日志

$ python receive_topic.py "*.critical" [*] Waiting for logs. Binding: ['*.critical']

消费者 3:接收所有日志(#)

$ python receive_topic.py "#" [*] Waiting for logs. Binding: ['#']**生产者:**```bash$ python emit_topic.py kern.critical "Kernel panic" [x] Sent kern.critical:Kernel panic$ python emit_topic.py app.critical "App crash" [x] Sent app.critical:App crash$ python emit_topic.py kern.info "Kernel info" [x] Sent kern.info:Kernel info

结果:

  • kern.critical 会被三个消费者都收到(匹配 kern.*, *.critical, #)。
  • app.critical 仅被消费者2和3收到。
  • kern.info 仅被消费者1和3收到。

Topic 交换机提供了极其强大的基于模式的消息路由,是构建事件驱动架构的利器。

8. 第六章:消息可靠性 —— 确认、持久化与发布者确认

生产环境中,消息不能丢。RabbitMQ 提供了三重保障:

  1. 消费者确认(Acknowledgement)
    :消费者告诉 RabbitMQ,消息已成功处理。我们已在工作队列中使用 basic_ack。
  2. 队列持久化(Durable)
    :RabbitMQ 重启后队列不丢失。queue_declare(queue='task_queue', durable=True)。
  3. 消息持久化
    :消息本身标记为持久,写入磁盘。properties=pika.BasicProperties(delivery_mode=2)。
  4. 发布者确认(Publisher Confirms)
    :生产者知道消息是否成功到达 RabbitMQ。

我们来改造工作队列,加入发布者确认和持久化。

可靠生产者 reliable_send.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()# 启用发布者确认channel.confirm_delivery()# 声明持久化队列channel.queue_declare(queue='durable_task', durable=True)for i in range(14):    message = f"Persistent Task {i}"# 将消息标记为持久化    properties = pika.BasicProperties(delivery_mode=2)try:        channel.basic_publish(exchange='',                              routing_key='durable_task',                              body=message,                              properties=properties)        print(f" [x] Confirmed: {message}")except pika.exceptions.UnroutableError:        print(f" [x] Failed to route: {message}")connection.close()

可靠消费者 reliable_worker.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.queue_declare(queue='durable_task', durable=True)defcallback(ch, method, properties, body):    print(f" [x] Received {body.decode()}")# 模拟处理import time    time.sleep(1)    print(f" [x] Done {body.decode()}")# 手动确认    ch.basic_ack(delivery_tag=method.delivery_tag)channel.basic_qos(prefetch_count=1)channel.basic_consume(queue='durable_task', on_message_callback=callback)print(' [*] Waiting for durable tasks...')channel.start_consuming()

运行演示

先启动 reliable_worker.py,再执行 reliable_send.py:

生产者输出:

$pythonreliable_send.py[x]Confirmed:PersistentTask1[x]Confirmed:PersistentTask2[x]Confirmed:PersistentTask3

现在即使重启 RabbitMQ(docker restart rabbitmq),队列和尚未被消费的持久化消息也不会丢失。

提示:持久化有性能开销,只对关键消息使用。

9. 第七章:高级应用 —— 死信队列与延迟队列

如何实现“订单30分钟未支付自动取消”这样的延迟任务?RabbitMQ 本身没有延迟队列,但可以用 死信交换机(DLX) 和 消息TTL(存活时间) 组合实现。

原理

  • 给队列设置 x-dead-letter-exchange 和 x-dead-letter-routing-key。当消息在该队列中变成死信(被拒绝、过期或队列满)时,会被自动转发到死信交换机。
  • 给消息设置 expiration (毫秒)。消息过期后会变成死信,从而被投递到指定的延迟队列。

延迟队列代码 delay_queue.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()# 1. 定义死信交换机dlx_exchange = 'dlx_exchange'channel.exchange_declare(exchange=dlx_exchange, exchange_type='direct')# 2. 死信队列(真正延迟后消费的队列)dlx_queue = 'delayed_queue'channel.queue_declare(queue=dlx_queue)channel.queue_bind(exchange=dlx_exchange, queue=dlx_queue, routing_key='delayed_key')# 3. 普通队列,设置死信参数和队列TTL(也可针对单独消息设TTL)args = {'x-dead-letter-exchange': dlx_exchange,'x-dead-letter-routing-key''delayed_key',# 'x-message-ttl': 5000  # 统一队列TTL 5秒,这里用消息TTL演示}normal_queue = 'normal_queue'channel.queue_declare(queue=normal_queue, arguments=args)# 生产者发送一条TTL为5秒的消息message = "Delayed order cancel"properties = pika.BasicProperties(expiration='5000')  # 消息TTL 5秒channel.basic_publish(exchange='', routing_key=normal_queue, body=message, properties=properties)print(f" [x] Sent to normal_queue with 5s TTL: {message}")# 消费者监听死信队列(即延迟后的队列)defconsume_delayed(ch, method, properties, body):    print(f" [x] Received delayed message at {time.strftime('%X')}{body.decode()}")    ch.basic_ack(delivery_tag=method.delivery_tag)import timeprint(f" [*] Start time: {time.strftime('%X')}")channel.basic_consume(queue=dlx_queue, on_message_callback=consume_delayed)channel.start_consuming()

运行与输出

$ python delay_queue.py [x] Sent to normal_queue with5s TTL: Delayedordercancel [*] Starttime14:32:10 [x] Received delayed message at14:32:15Delayedordercancel

时间上正好相差5秒,延迟消费达成!这个模式广泛应用于定时触发、超时处理等业务。

10. 第八章:RPC —— 远程过程调用

RPC 允许客户端将请求消息发送到队列,然后阻塞等待服务器返回响应。实现的关键是 correlation_id(关联ID)和 reply_to(回调队列)。

服务器 rpc_server.py

import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))channel = connection.channel()channel.queue_declare(queue='rpc_queue')defon_request(ch, method, props, body):    n = int(body)    print(f" [.] fib({n})")# 模拟计算斐波那契    response = fib(n)# 将结果发回给 props.reply_to 指定的回调队列    ch.basic_publish(exchange='',                     routing_key=props.reply_to,                     properties=pika.BasicProperties(correlation_id=props.correlation_id),                     body=str(response))    ch.basic_ack(delivery_tag=method.delivery_tag)deffib(n):if n == 0return0elif n == 1return1elsereturn fib(n-1) + fib(n-2)channel.basic_qos(prefetch_count=1)channel.basic_consume(queue='rpc_queue', on_message_callback=on_request)print(" [x] Awaiting RPC requests")channel.start_consuming()

客户端 rpc_client.py

import pikaimport uuidclassFibonacciRpcClient:def__init__(self):self.connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))self.channel = self.connection.channel()# 创建唯一的回调队列        result = self.channel.queue_declare(queue='', exclusive=True)self.callback_queue = result.method.queueself.channel.basic_consume(queue=self.callback_queue,                                   on_message_callback=self.on_response,                                   auto_ack=True)defon_response(self, ch, method, props, body):ifself.corr_id == props.correlation_id:self.response = body.decode()defcall(self, n):self.response = Noneself.corr_id = str(uuid.uuid4())self.channel.basic_publish(exchange='',                                   routing_key='rpc_queue',                                   properties=pika.BasicProperties(                                       reply_to=self.callback_queue,                                       correlation_id=self.corr_id,                                   ),                                   body=str(n))# 等待响应whileself.response is None:self.connection.process_data_events()return int(self.response)# 使用客户端fib_client = FibonacciRpcClient()print(" [x] Requesting fib(10)")response = fib_client.call(10)print(f" [.] Got {response}")

运行与输出

服务器:

$ python rpc_server.py [x] Awaiting RPC requests [.] fib(10)

客户端:

$ python rpc_client.py[x] Requesting fib(10)[.] Got 55

客户端发送请求后,阻塞等待来自自己专属回调队列的响应,通过 correlation_id 精准匹配请求与响应。这是典型的消息同步模式。

11. 结语与最佳实践

我们由浅入深地走完了 RabbitMQ 在 Python 中六大消息模式与高级特性。这些代码片段不仅是示例,更是可以直接复用到生产项目中的模板。最后,总结几条金科玉律:

  1. 多用临时队列,善用交换机
    :消费者尽量使用随机队列并绑定到交换机,实现组件间解耦。
  2. 生产者确认 + 消费者手动确认 + 持久化
    :三者缺一,高可靠无从谈起。auto_ack 仅在可容忍消息丢失的场景使用。
  3. 合理设置 prefetch_count
    :避免一个消费者被堆积的消息撑死,是实现公平调度的利器。
  4. 死信队列不仅是延迟任务
    :它还适用于收集处理异常的消息,方便排查和人工干预。
  5. 连接与通道管理
    :BlockingConnection 适合简单脚本,异步场景请用 AsyncioConnection 或 TornadoConnection。生产环境务必配置心跳自动重连
  6. 监控为王
    :善用 http://localhost:15672 管理界面,观察队列长度、消息速率、消费者数量,是调优和排错的眼睛。

消息队列是分布式系统的脊梁,而 RabbitMQ 这条脊梁足够强壮且灵活。掌握它,你就掌握了一种构建健壮、可扩展系统的核心能力。


*本文所有代码均基于 pika 1.3+ 和 RabbitMQ 3.12 编写,确保可直接运行。如有疑问,欢迎在评论区交流!*

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 19:31:32 HTTP/2.0 GET : https://f.mffb.com.cn/a/493269.html
  2. 运行时间 : 0.174238s [ 吞吐率:5.74req/s ] 内存消耗:4,966.06kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=41416d7a93c1d142714ad610dc9ceb8c
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000505s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000799s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000345s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000295s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000498s ]
  6. SELECT * FROM `set` [ RunTime:0.000207s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000592s ]
  8. SELECT * FROM `article` WHERE `id` = 493269 LIMIT 1 [ RunTime:0.026393s ]
  9. UPDATE `article` SET `lasttime` = 1783078292 WHERE `id` = 493269 [ RunTime:0.000516s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000223s ]
  11. SELECT * FROM `article` WHERE `id` < 493269 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000366s ]
  12. SELECT * FROM `article` WHERE `id` > 493269 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001987s ]
  13. SELECT * FROM `article` WHERE `id` < 493269 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002236s ]
  14. SELECT * FROM `article` WHERE `id` < 493269 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.013217s ]
  15. SELECT * FROM `article` WHERE `id` < 493269 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.058906s ]
0.175855s