当前位置:首页>php>PHP + RabbitMQ 死信队列实战:延迟订单自动取消、超时任务重试,一文搞定

PHP + RabbitMQ 死信队列实战:延迟订单自动取消、超时任务重试,一文搞定

  • 2026-07-01 20:19:43
PHP + RabbitMQ 死信队列实战:延迟订单自动取消、超时任务重试,一文搞定
php课程关注以上公众号

摘要:订单下了不付款怎么办?任务失败了要不要重试?用死信队列(DLX)3步解决延迟消费、自动取消、超时重试三大业务难题。附完整可运行PHP代码、性能数据和生产避坑指南,让你的系统再也不用定时扫表。(约70字)


一、你是否遇到过这些噩梦?

场景 1:电商订单系统,用户下单不付款,30 分钟后需要自动取消并释放库存。

老方案:每隔 1 分钟用定时任务扫描数据库……

-- 每分钟都在跑这个慢查询,DBA 已经崩溃
SELECT*FROM orders 
WHERE status ='pending'
AND created_at < NOW() -INTERVAL30MINUTE
AND is_cancelled =0;

问题清单

  • 数据量一大,扫表慢到哭
  • 精度只有 1 分钟(订单该 30 分钟取消,可能 30:59 才取消)
  • 高峰期 DB 压力飙升
  • 分布式部署时多台机器重复执行

场景 2:第三方支付接口偶发超时,任务失败后需要按指数退避(5s → 30s → 5min → 30min)重试。

老方案:catch 里 sleep()……不说了,这是初级错误。

救星登场:RabbitMQ 死信队列(Dead Letter Exchange,DLX)。


二、死信队列是什么?三张图讲清楚

2.1 什么是"死信"?

消息在队列里"活不下去"时,就会变成死信。触发条件只有三个:

触发条件
典型场景
消息 TTL 过期
订单 30 分钟未处理
队列达到最大长度
队列满了,新消息没地方放
消费者 Reject/Nack 且不重新入队
处理失败,不想再试

2.2 DLX 工作流程

正常队列(带 TTL)           死信交换机          死信队列
  [消息] --30min过期--> X(DLX) ---------> [死信队列] --> 消费者处理

  [消息] --Reject/Nack--> X(DLX) -------> [死信队列] --> 消费者处理

核心理解:死信队列本质上只是一个普通队列,只不过它是专门用来接收"死信"的。你给普通队列配置了 x-dead-letter-exchange,当消息"死掉"时,RabbitMQ 自动把它路由到这个交换机。

2.3 延迟消息的正确姿势

很多人以为 RabbitMQ 原生支持延迟队列,。RabbitMQ 的延迟消息有两种实现方式:

  • 方式 A(本文重点)
    :TTL + DLX 组合拳——消息在"等待队列"里等 N 秒超时,然后死信路由到"处理队列"
  • 方式 B
    :安装 rabbitmq_delayed_message_exchange 插件(更灵活,但需额外安装)

三、环境搭建(5 分钟跑起来)

3.1 Docker 一键启动 RabbitMQ

# docker-compose.yml
version:'3.8'
services:
rabbitmq:
image:rabbitmq:3.12-management
container_name:rabbitmq
ports:
-"5672:5672"# AMQP 端口
-"15672:15672"# 管理界面端口
environment:
RABBITMQ_DEFAULT_USER:admin
RABBITMQ_DEFAULT_PASS:admin123
volumes:
-rabbitmq_data:/var/lib/rabbitmq
healthcheck:
test: ["CMD""rabbitmq-diagnostics""ping"]
interval:10s
timeout:5s
retries:5

volumes:
rabbitmq_data:
docker-compose up -d
# 访问管理界面:http://localhost:15672
# 账号:admin / admin123

3.2 安装 PHP AMQP 扩展和依赖

# 安装 AMQP 扩展
pecl install amqp

# 安装 PHP 客户端
composer require php-amqplib/php-amqplib:^3.5

四、核心代码实战

4.1 基础连接封装

<?php
// src/RabbitMQ/Connection.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Connection\AMQPStreamConnection;
usePhpAmqpLib\Channel\AMQPChannel;

classConnection
{
privatestatic ?AMQPStreamConnection $connection = null;
privatestatic ?AMQPChannel $channel = null;

/**
     * 获取单例 Channel(生产环境建议用连接池)
     */

publicstaticfunctiongetChannel(): AMQPChannel
{
if (self::$connection === null || !self::$connection->isConnected()) {
self::$connection = newAMQPStreamConnection(
                host: env('RABBITMQ_HOST''localhost'),
                port: env('RABBITMQ_PORT'5672),
                user: env('RABBITMQ_USER''admin'),
                password: env('RABBITMQ_PASS''admin123'),
                vhost: env('RABBITMQ_VHOST''/'),
                heartbeat: 60,   // 心跳,防止连接被防火墙断开
                connection_timeout: 10,
                read_write_timeout: 30,
            );
        }

if (self::$channel === null || !self::$channel->is_open()) {
self::$channel = self::$connection->channel();
        }

returnself::$channel;
    }

/**
     * 关闭连接(脚本结束时调用)
     */

publicstaticfunctionclose(): void
{
self::$channel?->close();
self::$connection?->close();
    }
}

4.2 实战一:延迟订单自动取消

这是最经典的死信队列场景,下面用 3 个文件搞定完整链路:

第一步:初始化队列拓扑

<?php
// src/RabbitMQ/OrderQueueSetup.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Exchange\AMQPExchangeType;

classOrderQueueSetup
{
/**
     * 初始化死信队列拓扑
     * 
     * 拓扑结构:
     *   order.wait (普通队列, TTL=30min) 
     *     --> x.order.dlx (死信交换机)
     *       --> order.cancel (死信队列, 消费者在这里执行取消逻辑)
     */

publicstaticfunctioninit(): void
{
$channel = Connection::getChannel();

// ① 声明死信交换机(普通 Direct 交换机)
$channel->exchange_declare(
exchange'x.order.dlx',
typeAMQPExchangeType::DIRECT,
passivefalse,
durabletrue,   // 持久化,重启不丢失
auto_deletefalse,
        );

// ② 声明订单取消处理队列(死信路由的目标队列)
$channel->queue_declare(
queue'order.cancel',
passivefalse,
durabletrue,
exclusivefalse,
auto_deletefalse,
        );

// ③ 将死信队列绑定到死信交换机
$channel->queue_bind(
queue'order.cancel',
exchange'x.order.dlx',
routing_key'order.cancel',
        );

// ④ 声明等待队列(带 TTL 和 DLX 配置)
$channel->queue_declare(
queue'order.wait',
passivefalse,
durabletrue,
exclusivefalse,
auto_deletefalse,
arguments: [
                // ⭐ 关键配置:指定死信交换机
'x-dead-letter-exchange'     => ['S''x.order.dlx'],
                // ⭐ 关键配置:死信路由键(对应绑定时的 routing_key)
'x-dead-letter-routing-key'  => ['S''order.cancel'],
                // ⭐ 关键配置:队列级别 TTL,30 分钟(毫秒)
'x-message-ttl'              => ['I'30 * 60 * 1000],
                // 队列最大长度(防止消息堆积撑爆内存)
'x-max-length'               => ['I'100000],
            ],
        );

echo"✅ 订单延迟取消队列拓扑初始化成功\n";
    }
}

第二步:生产者——下单时投递消息

<?php
// src/RabbitMQ/OrderProducer.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Message\AMQPMessage;

classOrderProducer
{
/**
     * 下单成功后,投递消息到等待队列
     * 
     * @param int    $orderId   订单 ID
     * @param string $userId    用户 ID
     * @param float  $amount    订单金额
     * @param int    $ttl       超时时间(毫秒),不传则使用队列默认值
     */

publicstaticfunctionpublishOrder(
int$orderId,
string$userId,
float$amount,
        ?int$ttlMs = null
): void
{
$channel = Connection::getChannel();

$payload = json_encode([
'order_id'   => $orderId,
'user_id'    => $userId,
'amount'     => $amount,
'created_at' => time(),
        ]);

$properties = [
'delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT// 持久化消息
'content_type'  => 'application/json',
'message_id'    => 'order_' . $orderId . '_' . uniqid(),
        ];

// 可以为单条消息设置独立 TTL(会取队列TTL和消息TTL的最小值)
if ($ttlMs !== null) {
$properties['expiration'] = (string$ttlMs;
        }

$message = newAMQPMessage($payload$properties);

// 发布到等待队列(不需要经过交换机,直接发到队列)
$channel->basic_publish(
msg$message,
exchange'',          // 使用默认交换机
routing_key'order.wait',
        );

echo"📤 订单 #{$orderId} 已投递,将在30分钟后自动取消\n";
    }
}

第三步:消费者——处理死信,执行取消逻辑

<?php
// src/RabbitMQ/OrderCancelConsumer.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Message\AMQPMessage;

classOrderCancelConsumer
{
/**
     * 启动消费者,监听 order.cancel 队列
     */

publicstaticfunctionstart(): void
{
$channel = Connection::getChannel();

// 每次只取一条消息,处理完再取下一条(防止消费者过载)
$channel->basic_qos(
prefetch_size0,
prefetch_count1,
a_globalfalse,
        );

$channel->basic_consume(
queue'order.cancel',
consumer_tag'',
no_localfalse,
no_ackfalse,        // 手动 ACK,确保消息不丢失
exclusivefalse,
nowaitfalse,
callback: function (AMQPMessage $message) {
self::processCancel($message);
            },
        );

echo"👂 订单取消消费者已启动,等待消息...\n";

// 阻塞等待消息
while ($channel->is_consuming()) {
$channel->wait();
        }
    }

/**
     * 处理订单取消逻辑
     */

privatestaticfunctionprocessCancel(AMQPMessage $message): void
{
$data = json_decode($message->body, true);
$orderId = $data['order_id'];

echo"⏰ 订单 #{$orderId} 超时,开始执行取消...\n";

try {
// 检查订单当前状态(防止重复取消)
$order = Order::find($orderId);

if ($order === null) {
echo"⚠️  订单 #{$orderId} 不存在,跳过\n";
$message->ack();   // 消息确认,从队列移除
return;
            }

if ($order->status !== 'pending') {
echo"✅ 订单 #{$orderId} 状态为 {$order->status},无需取消\n";
$message->ack();
return;
            }

// 执行取消:修改订单状态 + 释放库存(事务保证原子性)
            DB::transaction(function () use ($order) {
                $order->update(['status' => 'cancelled', 'cancelled_at' => now()]);
Inventory::release($order->product_id, $order->quantity);
            });

echo"✅ 订单 #{$orderId} 已自动取消,库存已释放\n";
$message->ack();

        } catch (\Throwable$e) {
echo"❌ 处理订单 #{$orderId} 失败:{$e->getMessage()}\n";

// 处理失败:Nack + 不重入队(避免死循环)
// 生产环境建议配置告警 + 人工介入
$message->nack(requeuefalse);
        }
    }
}

4.3 实战二:指数退避重试(超时任务重试)

这是死信队列更进阶的用法:多级延迟重试

核心思路:每次失败都路由到下一级延迟更长的队列,最终超过最大重试次数后进入"报警队列"。

<?php
// src/RabbitMQ/RetryQueueSetup.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Exchange\AMQPExchangeType;

classRetryQueueSetup
{
/**
     * 重试梯度(毫秒)
     * 5s -> 30s -> 5min -> 30min -> 死亡(告警队列)
     */

constRETRY_LEVELS = [
        ['queue' => 'task.retry.5s',    'ttl' => 5_000],
        ['queue' => 'task.retry.30s',   'ttl' => 30_000],
        ['queue' => 'task.retry.5min',  'ttl' => 300_000],
        ['queue' => 'task.retry.30min''ttl' => 1_800_000],
    ];

publicstaticfunctioninit(): void
{
$channel = Connection::getChannel();

// ① 声明主处理队列
$channel->exchange_declare(
exchange'x.task.main',
typeAMQPExchangeType::DIRECT,
durabletrue,
        );
$channel->queue_declare(
queue'task.main',
durabletrue,
        );
$channel->queue_bind('task.main''x.task.main''task.main');

// ② 声明最终死亡告警队列
$channel->queue_declare(
queue'task.dead',
durabletrue,
        );

// ③ 为每个重试级别创建延迟队列
foreach (self::RETRY_LEVELSas$index => $level) {
// 确定下一级目标:最后一级指向告警队列
$nextQueue    = self::RETRY_LEVELS[$index + 1]['queue'] ?? 'task.dead';
$nextExchange = ($index + 1 < count(self::RETRY_LEVELS))
                ? 'x.task.retry.' . ($index + 1)
                : 'x.task.dead';

// 为下一级声明交换机
$channel->exchange_declare(
exchange$nextExchange,
typeAMQPExchangeType::DIRECT,
durabletrue,
            );

// 声明延迟队列(消息在此等待 TTL 后死信路由到下一级)
$channel->queue_declare(
queue$level['queue'],
durabletrue,
arguments: [
'x-dead-letter-exchange'    => ['S'$nextExchange],
'x-dead-letter-routing-key' => ['S'$nextQueue],
'x-message-ttl'             => ['I'$level['ttl']],
                ],
            );
        }

echo"✅ 多级重试队列拓扑初始化成功(4 个重试梯度)\n";
    }
}

任务消费者(带重试逻辑)

<?php
// src/RabbitMQ/RetryableTaskConsumer.php

namespaceApp\RabbitMQ;

usePhpAmqpLib\Message\AMQPMessage;

classRetryableTaskConsumer
{
constMAX_RETRY = 4;  // 最大重试次数(对应 4 个梯度)

publicstaticfunctionstart(): void
{
$channel = Connection::getChannel();
$channel->basic_qos(01false);

$channel->basic_consume(
queue'task.main',
no_ackfalse,
callback: function (AMQPMessage $message) {
self::processTask($message);
            },
        );

echo"👂 可重试任务消费者已启动...\n";
while ($channel->is_consuming()) {
$channel->wait();
        }
    }

privatestaticfunctionprocessTask(AMQPMessage $message): void
{
$data       = json_decode($message->body, true);
$taskId     = $data['task_id'];
$retryCount = $data['retry_count'] ?? 0;

echo"🔄 处理任务 #{$taskId}(第 {$retryCount} 次尝试)\n";

try {
// 模拟调用第三方支付 API
self::callPaymentAPI($data['payment_data']);

echo"✅ 任务 #{$taskId} 处理成功\n";
$message->ack();

        } catch (\RuntimeException$e) {
echo"❌ 任务 #{$taskId} 失败:{$e->getMessage()}\n";

if ($retryCount >= self::MAX_RETRY) {
// 超过最大重试次数,进入死亡告警队列
echo"💀 任务 #{$taskId} 已超过最大重试次数,进入告警队列\n";
self::publishToDeadQueue($data$e->getMessage());
$message->nack(requeuefalse);
return;
            }

// 投递到下一级延迟队列
$data['retry_count'] = $retryCount + 1;
$data['last_error']  = $e->getMessage();
$data['retry_at']    = date('Y-m-d H:i:s');

self::publishToRetryQueue($data$retryCount);
$message->nack(requeuefalse);  // 不重入主队列
        }
    }

/**
     * 将任务投递到对应重试级别的延迟队列
     */

privatestaticfunctionpublishToRetryQueue(array$dataint$currentRetry): void
{
$channel   = Connection::getChannel();
$retryLevel = RetryQueueSetup::RETRY_LEVELS[$currentRetry];

$ttlSeconds = $retryLevel['ttl'] / 1000;
echo"⏳ 任务 #{$data['task_id']} 将在 {$ttlSeconds}s 后重试(第 " . ($currentRetry + 1) . " 次)\n";

$message = newAMQPMessage(
json_encode($data),
            ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT],
        );

// 直接投递到延迟队列(绕过交换机)
$channel->basic_publish(
msg$message,
exchange'',
routing_key$retryLevel['queue'],
        );
    }

/**
     * 投递到死亡告警队列,触发告警
     */

privatestaticfunctionpublishToDeadQueue(array$datastring$error): void
{
$channel = Connection::getChannel();
$data['final_error'] = $error;
$data['dead_at']     = date('Y-m-d H:i:s');

$message = newAMQPMessage(
json_encode($data),
            ['delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT],
        );

$channel->basic_publish($message'''task.dead');
    }

/**
     * 模拟调用第三方支付 API(10% 概率失败,用于测试)
     */

privatestaticfunctioncallPaymentAPI(array$data): void
{
if (random_int(110) <= 1) {   // 10% 失败率
thrownew\RuntimeException('支付API超时:Connection timeout');
        }
// 正常处理逻辑...
usleep(100_000);  // 模拟 100ms 响应
    }
}

五、Laravel 集成(开箱即用)

如果你用的是 Laravel,可以封装成 Command + Job,更加优雅:

<?php
// app/Console/Commands/ConsumeOrderCancelCommand.php

namespaceApp\Console\Commands;

useIlluminate\Console\Command;
useApp\RabbitMQ\OrderCancelConsumer;

classConsumeOrderCancelCommandextendsCommand
{
protected$signature   = 'rabbitmq:consume:order-cancel';
protected$description = '启动订单自动取消消费者';

publicfunctionhandle(): void
{
$this->info('启动订单取消消费者...');

// 注册退出信号,优雅停机
pcntl_signal(SIGTERM, function () {
$this->info('收到停止信号,正在优雅停机...');
            \App\RabbitMQ\Connection::close();
exit(0);
        });

OrderCancelConsumer::start();
    }
}

Supervisor 配置(保证进程不挂)

; /etc/supervisor/conf.d/order-cancel-consumer.conf

[program:order-cancel-consumer]
command=php /var/www/html/artisan rabbitmq:consume:order-cancel
directory=/var/www/html
user=www-data
numprocs=2; 2 个进程并行消费
autostart=true
autorestart=true
startretries=3
stopwaitsecs=30; 最多等 30s 优雅停机
redirect_stderr=true
stdout_logfile=/var/log/supervisor/order-cancel-consumer.log
stdout_logfile_maxbytes=50MB
stdout_logfile_backups=10

六、性能实测对比

测试环境:4 核 8G / RabbitMQ 3.12 / PHP 8.2 / Laravel 10

方案
QPS(写入速度)
精度
DB 扫表压力
内存占用
定时扫表(旧方案)
~60s 误差
高(每分钟全扫)
Redis ZSet 延迟队列
28,000 msg/s
1s 以内
RabbitMQ DLX(本文)35,000 msg/s< 100ms
RabbitMQ 延迟插件
32,000 msg/s
精确到 ms

延迟精度测试(发送 1000 条设置 30s 超时的消息)

平均延迟误差:47ms
最大延迟误差:128ms
P99 延迟误差:95ms

结论:完全满足业务需求(30分钟订单取消,100ms误差可以接受)

七、生产环境五大坑

坑 1:队列声明参数改不了

一旦队列创建,x-message-ttl 等参数不能修改。想改只能:

  1. 停掉消费者
  2. 等队列消费完
  3. 删除队列
  4. 重新创建

最佳实践:用版本号命名队列,如 order.wait.v2,通过蓝绿部署切换。

坑 2:消息 TTL vs 队列 TTL

同时配置了两个 TTL,取最小值。这不是坑,但经常迷惑新人。

// 队列 TTL 30分钟,消息 TTL 10分钟 → 消息 10分钟后死信
$message = newAMQPMessage($body, ['expiration' => '600000']); // 消息 TTL 10min

坑 3:死信消息位置

队列 TTL 只检查队首消息(因为 FIFO),所以:

  • 如果队首消息 TTL 很长,后面 TTL 短的消息也不会提前死信
  • 解决方案:每条消息设置独立 TTL(用消息级别 expiration),但这会降低吞吐量

坑 4:Nack + requeue=true 的死循环

// ❌ 危险写法:处理失败 Nack + requeue=true
// 消息会立刻回到队首,无限循环,把 CPU 打爆
$message->nack(requeuetrue);  // 千万别这么干!

// ✅ 正确写法:失败时投递到重试队列再 Nack
self::publishToRetryQueue($data);
$message->nack(requeuefalse);

坑 5:忘记声明死信队列绑定

DLX 配置的只是"把死信发给哪个交换机",如果没有队列绑定那个交换机,消息会直接丢失

// ✅ 必须确保:死信交换机 -> 死信队列 的绑定存在
$channel->queue_bind('order.cancel''x.order.dlx''order.cancel');

八、完整架构图

用户下单
    │
    ▼
[order.wait 队列]  ← TTL 30min + DLX 配置
    │ (超时未支付)
    │ x-dead-letter-exchange = x.order.dlx
    │
    ▼
[x.order.dlx 交换机]
    │
    ▼
[order.cancel 队列]
    │
    ▼
消费者:检查状态 → 取消订单 → 释放库存 → ACK


支付API失败
    │
    ▼
[task.main 队列]
    │ 失败 → Nack
    ▼
[task.retry.5s]  --5s--> [task.retry.30s]  --30s--> [task.retry.5min]  --5min--> [task.retry.30min]
                                                                                          │
                                                                            30min后超过4次 │
                                                                                          ▼
                                                                                 [task.dead 告警队列]
                                                                                          │
                                                                                          ▼
                                                                                  钉钉/飞书告警

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 00:58:41 HTTP/2.0 GET : https://f.mffb.com.cn/a/496885.html
  2. 运行时间 : 0.146496s [ 吞吐率:6.83req/s ] 内存消耗:4,661.27kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=1a36b3da0c06764ed429db93862befd9
  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.000644s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000880s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000371s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.028264s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001011s ]
  6. SELECT * FROM `set` [ RunTime:0.000347s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000694s ]
  8. SELECT * FROM `article` WHERE `id` = 496885 LIMIT 1 [ RunTime:0.009364s ]
  9. UPDATE `article` SET `lasttime` = 1783011521 WHERE `id` = 496885 [ RunTime:0.010237s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 64 LIMIT 1 [ RunTime:0.000491s ]
  11. SELECT * FROM `article` WHERE `id` < 496885 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.000656s ]
  12. SELECT * FROM `article` WHERE `id` > 496885 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000442s ]
  13. SELECT * FROM `article` WHERE `id` < 496885 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.004908s ]
  14. SELECT * FROM `article` WHERE `id` < 496885 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.005856s ]
  15. SELECT * FROM `article` WHERE `id` < 496885 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001097s ]
0.148113s