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

Laragon中Nginx+PHP7.4环境下Laravel API并发cURL请求阻塞问题

Laravel API 并发请求阻塞问题排查与解决

环境配置

  • 操作系统:Windows(Laragon)
  • Web服务器:Nginx
  • PHP版本:PHP 7.4 NTS
  • 框架:Laravel

现象

  • Postman单请求Laravel API → 正常 ✅
  • cURL单请求Laravel API → 正常 ✅
  • cURL并发请求两个Laravel API → 阻塞 ❌
  • 混合Laravel API与模拟API并发请求 → 正常 ✅

问题核心分析

1. 为何并发请求会阻塞?

最常见的原因是Laravel默认文件Session的排他锁机制:
当同一个会话(携带相同Session ID)的多个请求并发时,第一个请求会锁定Session文件,后续请求必须等待锁释放才能执行。你的测试中,Postman可能使用多会话或未携带Session Cookie,而cURL默认复用Cookie(若之前请求生成了Session),导致并发请求触发锁阻塞。

其次可能是PHP-FPM进程数不足:如果pm.max_children设置过小,无法同时处理多个请求,会导致请求排队挂起。

另外需要注意:你提供的cURL代码是串行执行(先完成第一个请求再执行第二个),并非真正并发;若你是通过多进程/线程发送请求,核心问题还是Session锁或PHP-FPM资源限制。

2. 是否需要配置Nginx/PHP?

需要针对性调整,以下是具体解决方案:


解决方案

方案1:解决Session锁问题

(1)禁用API的Session中间件

如果你的API是无状态接口(不需要用户会话),直接移除API路由的Session中间件:
打开app/Http/Kernel.php,修改api中间件组:

protected $middlewareGroups = [
    'api' => [
        'throttle:api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        // 移除该行:\Illuminate\Session\Middleware\StartSession::class
    ],
];

(2)切换非阻塞Session驱动

若必须使用Session,改用Redis、数据库等支持并发的驱动,避免文件锁:
修改.env文件:

SESSION_DRIVER=redis

(需提前配置Redis服务并安装对应的PHP扩展)

(3)手动提前释放Session锁

对于不需要全程持有Session的请求,可在业务逻辑前手动释放锁:

public function getUsers()
{
    // 提前保存并释放Session锁
    session()->save();
    
    // 后续业务逻辑不再修改Session,不会触发锁
    return response()->json(User::all());
}

方案2:调整PHP-FPM进程配置

打开Laragon中PHP 7.4的www.conf文件(路径:laragon/bin/php/php-7.4.nts-Win32-vc15-x64/php-fpm.d/www.conf),调整以下参数:

pm = dynamic
pm.max_children = 20  # 根据机器配置调整,Windows建议10-20
pm.start_servers = 5
pm.min_spare_servers = 2
pm.max_spare_servers = 8

修改后重启Laragon的PHP-FPM服务。

方案3:实现真正的cURL并发请求

若需要通过代码发送并发请求,改用cURL多句柄实现:

<?php
class CurlRequest {
    public function sendConcurrentRequests($urls) {
        $mh = curl_multi_init();
        $handles = [];

        foreach ($urls as $url) {
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
            // 禁用Cookie,避免Session锁干扰
            curl_setopt($ch, CURLOPT_COOKIESESSION, true);
            curl_setopt($ch, CURLOPT_COOKIE, '');

            curl_multi_add_handle($mh, $ch);
            $handles[$url] = $ch;
        }

        $running = null;
        do {
            curl_multi_exec($mh, $running);
            curl_multi_select($mh);
        } while ($running > 0);

        $responses = [];
        foreach ($handles as $url => $ch) {
            $response = curl_multi_getcontent($ch);
            $responses[$url] = curl_errno($ch) 
                ? 'Curl error: ' . curl_error($ch) 
                : json_decode($response, true);
            
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }

        curl_multi_close($mh);
        return $responses;
    }
}

// 使用示例
$api = new CurlRequest();
$responses = $api->sendConcurrentRequests([
    'http://localhost/crm-api/api/v1/users',
    'http://localhost/crm-api/api/v1/products'
]);

foreach ($responses as $url => $response) {
    $path = basename(parse_url($url, PHP_URL_PATH));
    if (is_array($response)) {
        echo "<pre>{$path} API Response:\n";
        print_r($response);
        echo "</pre>";
    } else {
        echo "<pre>Error fetching {$url}: {$response}</pre>";
    }
}
?>

方案4:Nginx配置优化(可选)

打开Laragon的Nginx站点配置(laragon/etc/nginx/sites-available/auto.laragon.conf),确保worker资源足够:

worker_processes auto;
events {
    worker_connections 1024;
}

修改后重启Nginx服务。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:04:56