PHP项目接口超时如何设置处理

wen PHP项目 22

本文目录导读:

PHP项目接口超时如何设置处理

  1. 客户端请求超时设置(发起HTTP请求时)
  2. 服务端处理超时设置(PHP脚本执行)
  3. 数据库查询超时设置
  4. 综合处理方案(推荐)
  5. 最佳实践建议

在PHP项目中处理接口超时,需要从客户端发起请求服务端处理请求两个层面分别设置,以下是详细的配置和处理方案:

客户端请求超时设置(发起HTTP请求时)

cURL 方式

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://api.example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 总超时时间10秒
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 连接超时5秒
// 高级设置:传输速度限制
curl_setopt($ch, CURLOPT_LOW_SPEED_LIMIT, 1024); // 1024字节/秒
curl_setopt($ch, CURLOPT_LOW_SPEED_TIME, 10); // 持续10秒低于限速则超时
$response = curl_exec($ch);
if (curl_errno($ch)) {
    $error = curl_error($ch);
    // 处理超时错误
    if (curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) {
        echo "请求超时";
    }
}
curl_close($ch);

Guzzle HTTP 客户端

<?php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
$client = new Client([
    'timeout' => 10, // 总超时
    'connect_timeout' => 5, // 连接超时
    'read_timeout' => 8, // 读取超时
]);
try {
    $response = $client->get('http://api.example.com', [
        'timeout' => 10,
        'connect_timeout' => 5
    ]);
} catch (RequestException $e) {
    if ($e->hasResponse()) {
        $statusCode = $e->getResponse()->getStatusCode();
    }
    // 处理超时
    if ($e instanceof ConnectException) {
        echo "连接超时";
    }
    if ($e->getCode() == CURLE_OPERATION_TIMEDOUT) {
        echo "请求超时";
    }
}

file_get_contents 方式

<?php
$ctx = stream_context_create([
    'http' => [
        'timeout' => 10, // 超时时间(秒)
        'method' => 'GET'
    ]
]);
$result = @file_get_contents('http://api.example.com', false, $ctx);
if ($result === false) {
    echo "请求失败或超时";
}

服务端处理超时设置(PHP脚本执行)

set_time_limit() 函数

<?php
// 设置脚本最大执行时间
set_time_limit(30); // 30秒
// 设置为0表示无限制(不推荐生产环境)
// set_time_limit(0);
// 处理耗时操作
processLongTask();

max_execution_time 配置(php.ini)

; 修改 php.ini 文件
max_execution_time = 30
; 或者针对特定虚拟机
max_input_time = 60

使用 pcntl 实现更精确的控制

<?php
declare(ticks = 1);
// 超时回调函数
function timeout_handler($signo) {
    throw new Exception('脚本执行超时');
}
// 设置超时信号
pcntl_signal(SIGALRM, 'timeout_handler');
pcntl_alarm(10); // 10秒后触发
try {
    // 执行可能超时的操作
    while (true) {
        // 处理数据
    }
} catch (Exception $e) {
    echo "脚本执行超时: " . $e->getMessage();
} finally {
    pcntl_alarm(0); // 取消闹钟
}

数据库查询超时设置

<?php
// MySQL 示例
try {
    $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
    $pdo->setAttribute(PDO::ATTR_TIMEOUT, 5); // 设置连接超时
    // 执行超时查询
    $stmt = $pdo->prepare('SELECT SLEEP(20)');
    // MySQL 查询超时
    $pdo->exec("SET SESSION MAX_EXECUTION_TIME = 1000"); // 1秒(MySQL 5.7+)
    $stmt->execute();
} catch (PDOException $e) {
    echo "数据库操作超时: " . $e->getMessage();
}

综合处理方案(推荐)

使用重试机制

<?php
function requestWithRetry($url, $maxRetries = 3, $timeout = 10) {
    $retries = 0;
    $success = false;
    $result = null;
    while (!$success && $retries < $maxRetries) {
        try {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            $result = curl_exec($ch);
            if (curl_errno($ch) == CURLE_OPERATION_TIMEDOUT) {
                $retries++;
                // 指数退避策略
                $waitTime = pow(2, $retries);
                sleep($waitTime);
                continue;
            }
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if ($httpCode >= 200 && $httpCode < 300) {
                $success = true;
            }
            curl_close($ch);
        } catch (Exception $e) {
            $retries++;
            if ($retries >= $maxRetries) {
                throw $e;
            }
        }
    }
    return $result;
}

使用消息队列处理

<?php
// 使用 Redis 或 RabbitMQ 实现异步处理
// 接口立即返回,后台异步处理
public function handleAsyncRequest() {
    $jobData = ['type' => 'process', 'data' => $input];
    // 推送到消息队列
    Redis::lpush('queue:processing', json_encode($jobData));
    return ['status' => 'accepted', 'message' => '请求已接收'];
}

最佳实践建议

  1. 分层设置超时

    • 客户端超时 < 服务端超时 < 负载均衡器超时
    • 客户端10秒 < PHP 30秒 < Nginx 60秒
  2. 使用监控和报警

    // 记录超时日志
    function logTimeout($service, $timeout) {
        $log = [
            'time' => date('Y-m-d H:i:s'),
            'service' => $service,
            'timeout' => $timeout,
            'url' => $_SERVER['REQUEST_URI'] ?? ''
        ];
        file_put_contents('/var/log/timeout.log', json_encode($log) . PHP_EOL, FILE_APPEND);
    }
  3. 超时阈值设置建议

    • 普通API:5-10秒
    • 文件上传:30-60秒
    • 批量处理:根据数据量动态设置
    • 长连接/推送:使用 WebSocket 或 SSE
  4. 性能优化

    // 使用异步非阻塞方式
    // Swoole 或 ReactPHP 实现协程处理
    go(function () {
        $result = Co::exec("curl -s http://api.example.com", 5);
    });

选择合适的超时处理方案需要根据具体的业务场景、系统架构和性能要求来决定,对于关键业务,建议同时使用多种策略组合(超时+重试+降级)。

抱歉,评论功能暂时关闭!