PHP curl并发请求

前言

使用PHP的curl函数调用多个外部HTTP接口时,默认情况下是需要一个一个执行的,第一个请求结束后才会发起第二个请求,这样会显得效率低。如果各个请求之间没有强依赖关系,可以使用curl的multi系列函数来同时发起多个请求,这样可以节省很多时间,提高效率。

有很多资料说curl_multi是使用多线程来实现并发的,但事实上并不是,它仍然是单线程,只是用了系统的select I/O多路复用机制来实现并发。

测试环境

PHP 7.3

代码

<?php
function main() {
    $requests = [
        [
            'url' => 'https://www.baidu.com', // 请求URL
            'method' => 'GET', // 请求方法,支持GET和POST
            'header' => [], // 请求头
            'param' => ['i' => 0], // 请求参数
        ],
        [
            'url' => 'http://www.sdhaidhoasdhaihd.com',
            'method' => 'GET',
            'header' => [],
            'param' => ['i' => 1],
        ],
    ];
    $handles = [];

    foreach ($requests as $req) {
        $options = [
            CURLOPT_HEADER => false,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30,
        ];
        if (!empty($req['header'])) {
            $options[CURLOPT_HTTPHEADER] = $req['header'];
        }

        switch ($req['method']) {
            case 'GET':
                $options[CURLOPT_URL] = "{$req['url']}?" . http_build_query($req['param']);
                break;
            case 'POST':
                $options[CURLOPT_URL] = $req['url'];
                $options[CURLOPT_POST] = true;
                $options[CURLOPT_POSTFIELDS] = http_build_query($req['param']);
                break;
            default:
                exit("Unsupported method:{$req['method']}");
        }

        $ch = curl_init();
        curl_setopt_array($ch, $options);
        $handles[] = $ch;
    }

    $mh = curl_multi_init();
    foreach ($handles as $ch) {
        curl_multi_add_handle($mh, $ch);
    }

    /* 不断执行,直至所有请求完成 */
    do {
        $errCode = curl_multi_exec($mh, $running);
        usleep(100000); // 睡眠100毫秒,避免循环太快打满CPU
    } while ($errCode === CURLM_OK && $running > 0);

    /* 读取响应数据 */
    if ($errCode !== CURLM_OK) {
        echo "Execute error: " . curl_multi_strerror($errCode) . "\n";
    } else {
        while ($info = curl_multi_info_read($mh)) {
            $ch = $info['handle'];
            if ($info['result'] != CURLM_OK) {
                $httpCode = $info['result'];
                $httpBody = curl_error($ch);
            } else {
                $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
                $httpBody = curl_multi_getcontent($ch);
            }
            $index = array_search($ch, $handles, true);
            $requests[$index]['response'] = [
                'code' => $httpCode,
                'body' => $httpBody,
            ];
        }
    }

    foreach ($handles as $ch) {
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }
    curl_multi_close($mh);

    /* 打印结果 */
    var_dump($requests);
}

main();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值