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

PHP curl_multi_exec批量请求随机跳过结果的异常排查

问题描述

使用curl_multi_exec()批量请求API,所有请求无报错且结果均存在,但在基于原$items数组遍历返回结果$res时,会随机跳过部分条目;但第三次遍历所有条目又能正常读取。相关代码如下:

function curl_multi ( array $apiUrls ) {

    $multiHandles = [];
    $results = [];

    // Initialize multi-handle
    $multiHandle = curl_multi_init();

    foreach ($apiUrls as $item => $url) {
        $ch = curl_init($url);

        // Set cURL options
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        //curl_setopt($ch, CURLOPT_TIMEOUT, 3);
        curl_setopt( $ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); 
        curl_setopt( $ch, CURLOPT_TCP_FASTOPEN, true); 
        curl_setopt( $ch, CURLOPT_ENCODING,  ''); 

        // Add individual handle to the multi-handle
        curl_multi_add_handle($multiHandle, $ch);

        $multiHandles[$item] = $ch;
    }

    // Execute multi-handle requests
    do {
        $status = curl_multi_exec($multiHandle, $active);
        curl_multi_select($multiHandle); // Non-blocking wait
    } while ($status === CURLM_CALL_MULTI_PERFORM || $active);

    // Process responses and close handles
    foreach ($multiHandles as $item => $ch) {
        $response = curl_multi_getcontent($ch);
        if ($response === false) { apiErr( "error $item > $apiUrls[$item]", curl_error($ch) );  } 
        else { $results[$item] = json_decode( $response, true ); }

        curl_multi_remove_handle($multiHandle, $ch);
        curl_close($ch);
    }

    // Close the multi-handle
    curl_multi_close($multiHandle);

    return $results;
}

foreach( $items as $item ) { $apiUrls[$item] = "https://..."; } 
$res = curl_multi ( $apiUrls );

foreach( $items as $item ) {
 // do something with each $res[$item]
 // some items are skipped, even if they exists!
}
异常原因分析

核心问题出在**json_decode失败导致对应条目值为null**,结合你遍历循环的判断逻辑引发了“跳过”假象:

  • 当部分API返回的响应不是合法JSON格式时,json_decode($response, true)会返回null,此时$results[$item]被赋值为null,但数组的键$item是真实存在的。
  • 如果第二个循环中的处理代码是类似if ($res[$item]) { ... }的布尔判断,PHP会将null解析为false,导致该条目被逻辑上“跳过”;但实际上数组键并未丢失,所以第三次遍历(比如改用array_key_exists($item, $res)检查键是否存在,或直接访问键而不做布尔判断)时,就能正常读取到null值。
  • 这种“随机跳过”的表现,本质是API返回的JSON合法性不稳定——部分请求的响应格式不符合JSON规范,导致json_decode失败。
验证与修复建议
  1. 验证原因:在第二个循环中添加var_dump($res[$item]),会发现被跳过的条目值均为null,同时可打印对应API的$response内容,确认是否为合法JSON。
  2. 修复方案:
    • 增加json_decode的错误检测,避免直接赋值null:
      else {
          $decoded = json_decode($response, true);
          if (json_last_error() !== JSON_ERROR_NONE) {
              apiErr("JSON decode error $item > $apiUrls[$item]", json_last_error_msg());
              $results[$item] = $response; // 或设置自定义默认值
          } else {
              $results[$item] = $decoded;
          }
      }
      
    • 修改遍历循环的判断逻辑,改用键存在性检查替代值的布尔判断:
      foreach( $items as $item ) {
          if (array_key_exists($item, $res)) {
              // 处理$res[$item]的逻辑
          }
      }
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 15:58:08