首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使多个请求的Amphp池/队列?那Curl处理人呢?

如何使多个请求的Amphp池/队列?那Curl处理人呢?
EN

Stack Overflow用户
提问于 2017-10-05 18:49:48
回答 1查看 1.6K关注 0票数 0

有一个使用GuzzleHttp编写的示例/测试代码:

代码语言:javascript
复制
use GuzzleHttp\Client;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use GuzzleHttp\Pool;
use Psr\Http\Message\ResponseInterface;

require __DIR__ . '/vendor/autoload.php';

$handler = new CurlHandler();

$stack = new HandlerStack($handler);
$stack->push(Middleware::httpErrors(), 'http_errors');
$stack->push(Middleware::redirect(), 'allow_redirects');
$stack->push(Middleware::cookies(), 'cookies');
$stack->push(Middleware::prepareBody(), 'prepare_body');
$interval = 100;
$concurrency = 50;
$client = new Client(['handler' => $stack]);
echo sprintf("Using Guzzle handler %s\n", get_class($handler));
echo sprintf("Printing memory usage every %d requests\n", $interval);
echo "Fetching package list... ";

$packageNames = json_decode(
    $client->get('https://packagist.org/packages/list.json')
           ->getBody()
           ->getContents()
)->packageNames;

if (empty($packageNames)) {
    echo "Empty result. No reason to continue.";
    return;
}

echo 'done. (' . count($packageNames) . " packages)\n\n";

$requests = function($packageNames) {
    foreach ($packageNames as $packageVendorPair) {
        yield new GuzzleHttp\Psr7\Request('GET', "https://packagist.org/p/{$packageVendorPair}.json");
    }
};

$pool = new Pool($client, $requests($packageNames), [
    'concurrency' => $concurrency,
    'fulfilled' => function (ResponseInterface $response, $index) use (&$counter, $interval) {
        $counter++;
        if ($counter % $interval === 0) {
            echo sprintf(
                "Processed %s requests. Memory used: %s MB\n",
                number_format($counter),
                number_format(memory_get_peak_usage()/1024/1024, 3)
            );
        }
    },
    'rejected' => function($reason, $index) use (&$counter, $interval)
    {
        $counter++;
        if ($counter % $interval === 0) {
            echo sprintf(
                'Processed %s requests. Memory used: %s MB',
                number_format($counter),
                number_format(memory_get_peak_usage()/1024/1024, 3)
            );
        }
    }
]);

$promise = $pool->promise();
$response = $promise->wait();

如何为Amphp或阿罗特制作类似的东西?我搜索了安培文档和堆栈溢出,但找不到类似的东西。

顺便说一句,我还发现安培不使用Curl作为处理程序。不明白为什么没有这样的选择。您能手动添加它吗?或者有更好的功能,什么取代了curl功能(各种自定义标题、调试/详细的可能性等等)?

我需要帮助的特定点:

  1. 有没有可能有人可以告诉我,在哪里可以找到用use框架或它的任何一个库创建的池等效示例,或者仅仅在更简单的示例中显示它?
  2. 安培中的Curl处理程序在哪里?我能用吗?怎么用?

Amphp网站上说:

如果堆栈溢出社区足够通用,它可以回答您的问题。使用amphp标签,让正确的人找到你的问题。

因为我提供了足够简单(和工作)的例子,所以我认为很容易理解我所需要的东西。

,恕我直言。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-05 20:36:28

没有相同的池,但是可以使用信号量和异步协同器来编写。

代码语言:javascript
复制
<?php

use Amp\Artax\DefaultClient;
use Amp\Loop;
use Amp\Sync\LocalSemaphore;

require __DIR__ . "/vendor/autoload.php";

Loop::run(function () {
    $concurrency = 10;
    $client = new DefaultClient;
    $semaphore = new LocalSemaphore(10);

    $packageResponse = yield $client->request("https://packagist.org/packages/list.json");
    $packageNames = json_decode(yield $packageResponse->getBody())->packageNames;

    $requestHandler = Amp\coroutine(function ($package) use ($client) {
        $url = "https://packagist.org/p/{$package}.json";

        $response = yield $client->request($url);
        $body = yield $response->getBody();

        return $body;
    });

    $counter = 0;

    foreach ($packageNames as $package) {
        $lock = yield $semaphore->acquire();

        $promise = $requestHandler($package);
        $promise->onResolve(function ($error, $body) use (&$counter, $lock) {
            $lock->release();

            if (++$counter % 50 === 0) {
                echo sprintf(
                    "Processed %s requests. Memory used: %s MB\n",
                    number_format($counter),
                    number_format(memory_get_peak_usage()/1024/1024, 3)
                );
            }
        });
    }
});

此示例使用LocalSemaphore实现,它是Amp\Sync\Semaphore的实现。信号量用于限制并发性。

在Amp中没有Curl处理程序,因为它不能很好地处理事件循环。Curl有自己的事件循环,但这只允许多个并发HTTP请求,没有其他非阻塞的I/O。这就是为什么Artax基于原始PHP套接字实现HTTP,而不依赖Curl。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46592802

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档