Php 建议:800万发送请求

Php 建议:800万发送请求,php,linux,curl,parallel-processing,request,Php,Linux,Curl,Parallel Processing,Request,我被编码成一个php机器人。现在我想发送一个800万的请求。是的,例如: 我使用multi_curl*但是有问题 我使用linux并行程序库解决问题 也许你有什么建议 Php 7.1.1、Linux Ubuntu 16.0.1 myfnc(){ i=1264609 echo "$(($1+i))"; response=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost/botum/i

我被编码成一个php机器人。现在我想发送一个800万的请求。是的,例如:

我使用multi_curl*但是有问题

我使用linux并行程序库解决问题

也许你有什么建议

Php 7.1.1、Linux Ubuntu 16.0.1

myfnc(){
    i=1264609
 echo "$(($1+i))";
 response=$(curl --write-out %{http_code} --silent --output /dev/null http://localhost/botum/index.php?i=$(($1+i)))
 echo $response
}
export -f myfnc
seq 100 | parallel -j0 myfnc
多旋度问题:

set_time_limit(0);
ini_set("max_execution_time",-1);
$nodes = array();

for($i =1366295;$i<1396296;$i++){
    array_push($nodes,"http://165.227.152.138/botum2/index.php?i=$i");
}

$node_count = count($nodes);

$curl_arr = array();
$master = curl_multi_init();

for($i = 0; $i < $node_count; $i++)
{
    $url =$nodes[$i];
 //problems code start
    $curl_arr[$i] = curl_init($url);
    curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, true);
//problems code end
    curl_multi_add_handle($master, $curl_arr[$i]);

}

do {
    curl_multi_exec($master,$running);
} while($running > 0);


for($i = 0; $i < $node_count; $i++)
{
    $results[] = curl_multi_getcontent  ( $curl_arr[$i]  );
}
print_r($results);
设置时间限制(0);
ini_集(“最大执行时间”,-1);
$nodes=array();
(i=1366295美元;i=0美元);
对于($i=0;$i<$node_count;$i++)
{
$results[]=curl_multi_getcontent($curl_arr[$i]);
}
打印(结果);

您的curl代码正试图同时启动130万个curl句柄,显然会耗尽资源(但您没有发现这一点,因为您没有检查curl\u init()的返回值,如果您执行了类似于
if(!($curl\u arr[$i]=curl\u init($url)){抛出新的\RuntimeException(“curl\u init failed!”)}
那么你会注意到的)

此外,这里使用的是忙循环

do {
    curl_multi_exec($master,$running);
} while($running > 0);
这意味着在执行句柄时,您将使用100%的cpu,而不是出于任何该死的原因,而您应该一直使用curl\u multi\u select等待

这是curl_multi的工作,但你只是用错了。我的建议是稍微修改代码

这将处理800万个请求,在响应完成时打印响应,并且不会同时使用超过500个连接,并使用异步选择()方法在等待网络IO时不使用任何cpu

curl_multi_fetch_and_print("http://165.227.152.138/botum2/index.php?i=",8000000,500,10000,true,true);
function curl_multi_fetch_and_print(string $base_url, int $count, int $max_connections, int $timeout_ms = 10000, bool $consider_http_300_redirect_as_error = true, bool $print_fault_reason): void
{
    if ($max_connections < 1) {
        throw new InvalidArgumentException("max_connections MUST be >=1");
    }
    if ($count < 1) {
        throw new InvalidArgumentException("count MUST be >=1");
    }
    $mh = curl_multi_init();
    $workers = array();
    $work = function () use (&$workers, &$mh, &$print_fault_reason) {
        // > If an added handle fails very quickly, it may never be counted as a running_handle
        while (1) {
            curl_multi_exec($mh, $still_running);
            if ($still_running < count($workers)) {
                break;
            }
            $cms = curl_multi_select($mh, 10);
            //var_dump('sr: ' . $still_running . " c: " . count($workers)." cms: ".$cms);
        }
        while (false !== ($info = curl_multi_info_read($mh))) {
            //echo "NOT FALSE!";
            //var_dump($info);
            {
                if ($info['msg'] !== CURLMSG_DONE) {
                    continue;
                }
                if ($info['result'] !== CURLM_OK) {
                    if ($print_fault_reason) {
                        echo "request #" . ($workers[(int)$info['handle']]) . " error: " . print_r(array(false, $info['result'], "curl_exec error " . $info['result'] . ": " . curl_strerror($info['result'])), true) . PHP_EOL;
                    }
                } elseif (CURLE_OK !== ($err = curl_errno($info['handle']))) {
                    if ($print_fault_reason) {
                        echo "request #" . ($workers[(int)$info['handle']]) . " error: " . print_r(array(false, $err, "curl error " . $err . ": " . curl_strerror($err)), true) . PHP_EOL;
                    }
                } else {
                    $code = (string)curl_getinfo($info['handle'], CURLINFO_HTTP_CODE);
                    if ($code[0] === "3") {
                        if ($consider_http_300_redirect_as_error) {
                            if ($print_fault_reason) {
                                echo "request #" . ($workers[(int)$info['handle']]) . " error: " . print_r(array(false, -1, "got a http " . $code . " redirect, which is considered an error"), true) . PHP_EOL;
                            }
                        } else {
                            //if ($print_fault_reason) {
                            //    echo "request #" . ($workers[(int)$info['handle']]) . " success: " . print_r(array(true, 0, "got a http " . $code . " redirect, which is considered a success"), true).PHP_EOL;
                            //} else {
                            // ... got a http redirect, which is not considered an errror,
                            echo "request #" . ($workers[(int)$info['handle']]) . " success: (http {$code} redirect)\n";
                            //}
                        }
                    } elseif ($code[0] === "2") {
                        if ($print_fault_reason) {
                            echo "request #" . ($workers[(int)$info['handle']]) . " success: http {$code}: " . curl_multi_getcontent($info['handle']) . PHP_EOL;
                        } else {
                            echo "request #" . ($workers[(int)$info['handle']]) . ": " . curl_multi_getcontent($info['handle']) . PHP_EOL;
                        }
                    } else {
                        // all non-2xx and non-3xx are always considered errors (500 internal server error, 400 client error, 404 not found, etcetc)
                        if ($print_fault_reason) {
                            echo "request #" . ($workers[(int)$info['handle']]) . " error: " . print_r(array(false, -1, "got a http " . $code . " code, which is considered an error"), true) . PHP_EOL;
                        }
                    }
                }
                curl_multi_remove_handle($mh, $info['handle']);
                assert(isset($workers[(int)$info['handle']]));
                unset($workers[(int)$info['handle']]);
                curl_close($info['handle']);
            }
        }
        //echo "NO MORE INFO!";
    };
    for ($i = 0; $i < $count; ++$i) {
        $url = $base_url . $i;
        while (count($workers) >= $max_connections) {
            //echo "TOO MANY WORKERS!\n";
            $work();
        }
        $neww = curl_init($url);
        if (!$neww) {
            trigger_error("curl_init() failed! probably means that max_connections is too high and you ran out of resources", E_USER_WARNING);
            if ($print_fault_reason) {
                echo "request #{$i} error: curl_init() failed!" . PHP_EOL;
            }
            continue;
        }
        $workers[(int)$neww] = $url;
        curl_setopt_array($neww, array(
            //CURLOPT_NOBODY => 1,
            CURLOPT_RETURNTRANSFER=>1,
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_TIMEOUT_MS => $timeout_ms
        ));
        curl_multi_add_handle($mh, $neww);
        //curl_multi_exec($mh, $unused_here); LIKELY TO BE MUCH SLOWER IF DONE IN THIS LOOP: TOO MANY SYSCALLS
    }
    while (count($workers) > 0) {
        //echo "WAITING FOR WORKERS TO BECOME 0!";
        //var_dump(count($workers));
        $work();
    }
    curl_multi_close($mh);
    return;
}
curl\u multi\u fetch\u和\u print(“http://165.227.152.138/botum2/index.php?i=“,80000050010000,对,对);
函数curl\u multi\u fetch\u和\u print(字符串$base\u url,int$count,int$max\u connections,int$timeout\u ms=10000,bool$consupt\u http\u 300\u redirect\u as\u error=true,bool$print\u fault\u reason):void
{
如果($最大连接数<1){
抛出新的InvalidArgumentException(“最大连接数必须大于等于1”);
}
如果($count<1){
抛出新的InvalidArgumentException(“计数必须大于等于1”);
}
$mh=curl_multi_init();
$workers=array();
$work=function()使用(&$workers、&$mh、&$print\u fault\u reason){
//>如果添加的句柄很快失败,它可能永远不会被视为正在运行的句柄
而(1){
curl_multi_exec($mh,$still_running);
如果($仍在运行<计数($工人)){
打破
}
$cms=卷曲多点选择($mh,10);
//变量转储('sr:'.$仍在运行。'c:.计数($workers)。“cms:.$cms”);
}
while(false!=($info=curl\u multi\u info\u read($mh))){
//回声“不假!”;
//var_dump($info);
{
如果($info['msg']!==CURLMSG_DONE){
持续
}
如果($info['result']!==CURLM_OK){
如果($print\u fault\u reason){
echo“request#”。($workers[(int)$info['handle']])。错误:“.print_r(数组(false,$info['result']),“curl_exec error”。$info['result']。:”。curl_strerror($info['result']),true)。PHP_EOL;
}
}elseif(CURLE\u OK!=($err=curl\u errno($info['handle'])){
如果($print\u fault\u reason){
echo“request#”。($workers[(int)$info['handle']])。错误:“.print_r(数组(false,$err,“curl error”。$err:”。curl_strerror($err)),true)。PHP_EOL;
}
}否则{
$code=(字符串)curl\u getinfo($info['handle',CURLINFO\u HTTP\u code);
如果($code[0]=“3”){
如果($将\u http\u 300\u重定向\u视为\u错误){
如果($print\u fault\u reason){
echo“request#”。($workers[(int)$info['handle']])。错误:“.print_r(数组(false,-1,“得到了一个http“$code.”重定向,这被认为是一个错误),true);
}
}否则{
//如果($print\u fault\u reason){
//echo“request#”。($workers[(int)$info['handle']])。“success:”.print_r(数组(true,0,“获得了一个http.$code.”重定向,这被认为是成功的),true);
//}否则{
//…获得http重定向,这不被视为错误,
echo“request#”。($workers[(int)$info['handle']])。“成功:(http{$code}重定向)\n”;
//}
}
}elseif($code[0]=“2”){
如果($print\u fault\u reason){
echo“request#”。($workers[(int)$info['handle']])。成功:http{$code}:“.curl_multi_getcontent($info['handle'])。PHP_EOL;
}否则{
echo“request#”。($workers[(int)$info['handle']]):“。curl\u multi\u getcontent($info['handle'])。PHP_EOL;
}
}否则{
//所有非2xx和非3xx始终被视为错误(500个内部服务器错误、400个客户端错误、404未找到等)
如果($print\u fault\u reason){
echo“request#”。($workers[(int)$info['handle']])。错误:“.print_r(数组(false,-1,“得到了一个http“$code.”代码,这被认为是一个错误),true);
}
}
}
卷曲多重移除手柄($mh,$info['handle']);
断言(isset($workers[(int)$info['handle']]);
未设置($workers[(int)$info['handle']]);
卷曲关闭($info['handle']);
}
}
//回声“没有更多信息!”;
};
对于($i=0;$i<$count;++$i){
$url=$base\u url.$i;
while(计数($workers)>=$max\u连接数){
//回应“工人太多!\n”;