You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP脚本调用CoinMarketCap API响应迟缓,请求排查原因

解决CoinMarketCap API在PHP脚本中响应缓慢的问题

嘿,我看了你的问题和代码,发现问题大概率出在串行API请求上——如果你的$config里配置了多种加密货币,每次调用convertData都会单独发起一次curl请求,这些请求是一个接一个等待完成的,总耗时就是所有请求时间的累加,这正好匹配你说的页面加载11-13秒的情况(毕竟单独请求快,但多个串行就慢了)。

下面给你几个针对性的优化方案,按实现难度和效果排序:

1. 先加本地缓存(最快见效)

CoinMarketCap的行情数据不会每秒都更新,完全可以把请求到的数据缓存起来,比如缓存5分钟,这样大部分页面请求都不用真的去调用API,直接读本地缓存就行,速度会飞起来。

修改你的fetchData函数,加上缓存逻辑:

function fetchData($currency) {
    // 定义缓存文件路径和过期时间(这里设为5分钟=300秒)
    $cacheDir = __DIR__ . '/api_cache';
    $cacheFile = $cacheDir . '/' . $currency . '.json';
    $cacheExpire = 300;

    // 检查缓存是否有效
    if (file_exists($cacheFile) && (time() - filemtime($cacheFile)) < $cacheExpire) {
        $response = file_get_contents($cacheFile);
        return json_decode($response, true);
    }

    // 缓存失效,发起API请求
    $curl = curl_init();
    curl_setopt_array($curl, array(
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_URL => 'https://api.coinmarketcap.com/v1/ticker/'.$currency.'/?convert=EUR',
        CURLOPT_TIMEOUT => 10, // 设置超时,避免请求卡住
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' // 加个UA,避免被限流
    ));

    $response = curl_exec($curl);
    // 处理请求失败的情况:如果有旧缓存就用旧的,否则返回空数组
    if (curl_errno($curl)) {
        if (file_exists($cacheFile)) {
            $response = file_get_contents($cacheFile);
        } else {
            $response = json_encode([]);
        }
    }
    curl_close($curl);

    // 创建缓存目录(如果不存在)并写入缓存
    if (!is_dir($cacheDir)) {
        mkdir($cacheDir, 0755, true);
    }
    file_put_contents($cacheFile, $response);

    return json_decode($response, true);
}

2. 改用并行请求(适合需要准实时数据的场景)

如果你的业务需要相对新的数据,不想依赖缓存,那可以用curl_multi批量发起所有API请求,让这些请求同时进行,总耗时会接近单个请求的时间,而不是累加。

先写一个批量请求的函数:

function fetchMultipleCurrencies($currencies) {
    $multiHandle = curl_multi_init();
    $curlHandles = [];
    $results = [];

    // 初始化所有curl请求
    foreach ($currencies as $currency) {
        $url = 'https://api.coinmarketcap.com/v1/ticker/'.$currency.'/?convert=EUR';
        $curlHandles[$currency] = curl_init();
        curl_setopt_array($curlHandles[$currency], array(
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_URL => $url,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        ));
        curl_multi_add_handle($multiHandle, $curlHandles[$currency]);
    }

    // 执行并行请求
    $running = null;
    do {
        curl_multi_exec($multiHandle, $running);
        curl_multi_select($multiHandle);
    } while ($running > 0);

    // 收集结果并清理资源
    foreach ($curlHandles as $currency => $handle) {
        $results[$currency] = json_decode(curl_multi_getcontent($handle), true);
        curl_multi_remove_handle($multiHandle, $handle);
        curl_close($handle);
    }
    curl_multi_close($multiHandle);

    return $results;
}

然后修改你的业务逻辑,先一次性拉取所有需要的货币数据,再处理:

// 先获取所有配置的货币列表
$targetCurrencies = array_keys($config);
// 批量拉取数据
$allMarketData = fetchMultipleCurrencies($targetCurrencies);

// 修改convertData函数,直接用批量获取的数据
function convertData($currency) {
    global $config, $allMarketData;
    $response = $allMarketData[$currency];
    // 下面的逻辑和你原来的一样,不用再调用fetchData了
    $id = $response[0]['id'];
    $name = $response[0]['name'];
    $value = $response[0]['price_eur'];
    $perc_change_h = $response[0]['percent_change_1h'];
    $perc_change_d = $response[0]['percent_change_24h'];
    $perc_change_w = $response[0]['percent_change_7d'];
    $amount = $config[$currency]['amount'];
    $starting_price = $config[$currency]['starting_price'];
    $spend = $amount * $starting_price;
    $total = $amount * $value;
    $profit = $total - $spend;
    return array(
        'id' => $id,
        'name' => $name,
        'value' => round($value, 4),
        'change_hour' => $perc_change_h,
        'change_day' => $perc_change_d,
        'change_week' => $perc_change_w,
        'amount' => $amount,
        'starting' => number_format($starting_price, 4),
        'spend' => number_format($spend, 2),
        'total' => number_format($total, 2),
        'profit' => number_format($profit, 2)
    );
}

3. 其他小优化

  • 给curl设置合理的超时时间(比如10秒),避免某个请求卡住拖慢整个页面
  • 给请求加一个User-Agent,有些API会限制无UA的请求
  • 检查你的服务器是否开启了curl的keep-alive(默认应该开启),减少TCP握手的时间

这两个方案结合起来用效果最好:平时读缓存,缓存过期时用并行请求更新缓存,既保证速度又能拿到较新的数据。

内容的提问来源于stack exchange,提问作者Kazuto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:46:00