fansipan / peak
使用 PSR-18 客户端实现并发发送 HTTP 请求的简单高效解决方案。
Requires
- php: ^8.1
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
Requires (Dev)
- amphp/pipeline: ^1.0
- azjezz/psl: ^2.7
- clue/mq-react: ^1.6
- fansipan/fansipan: ^0.6
- fansipan/mock-client: ^1.0
- friendsofphp/php-cs-fixer: ^3.15
- guzzlehttp/guzzle: ^7.5
- phpbench/phpbench: ^1.2
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^9.0
- react/async: ^4.1
- react/http: ^1.9
- symfony/http-client: ^6.3
Suggests
- azjezz/psl: Required for the PSL driver
- clue/mq-react: Required for the ReactPHP driver
- php-http/discovery: Provides a convenient solution for auto-discovery and auto-installation of well-known implementations of PSR-17 (HTTP Factories), PSR-18 (HTTP Clients)
- react/async: Required for the ReactPHP driver
This package is auto-updated.
Last update: 2024-09-05 15:04:35 UTC
README
使用 PSR-18 客户端实现并发发送 HTTP 请求的简单高效解决方案。
Peak 是一个库,它通过请求池实现并发请求发送。它利用 AMPHPC、ReactPHP 或 PSL 的事件循环来并发处理和管理工作请求。
要求
- PHP 8.1 或更高版本。
- 一个支持底层使用 Fibers 进行非阻塞 I/O 的包(现在称为 驱动器)。
安装
您可以通过 composer 安装此包。
composer require fansipan/peak
此外,根据您的驱动器选择,可能还需要安装以下包。
AMPHPC
composer require amphp/pipeline
PSL
composer require azjezz/psl
ReactPHP
composer require clue/mq-react react/async
使用
创建请求池
典型应用程序会使用 PoolFactory
类来创建一个池。
use Fansipan\Peak\PoolFactory; /** @var \Psr\Http\Client\ClientInterface $client */ $pool = PoolFactory::createForClient($client);
它将尝试使用 AsyncClientFactory
创建客户端的异步版本。支持的客户端包括 Guzzle 和 Symfony HTTPClient (Psr18Client
)。
您可以使用任何与 ReactPHP 驱动器兼容的 PSR-18 客户端实现。如果使用不支持的客户端,它将被替换为
Browser
HTTP 客户端(需要安装react/http
)。
Fansipan\Peak\PoolFactory
提供了一个基于已安装包的配置请求池,这对于大多数情况都是合适的。但是,如果您希望,您也可以指定特定的实现,如果它在您的平台和/或应用程序中可用。
首先,您需要创建所需的驱动器
use Fansipan\Peak\Concurrency\AmpDeferred; use Fansipan\Peak\Concurrency\PslDeferred; use Fansipan\Peak\Concurrency\ReactDeferred; // AMPHP $defer = new AmpDeferred(); // PSL $defer = new PslDeferred(); // ReactPHP $defer = new ReactDeferred();
然后创建一个异步客户端,它实际上是 PSR-18 客户端的装饰器
use Fansipan\Peak\Client\GuzzleClient; use Fansipan\Peak\Client\SymfonyClient; use Fansipan\Peak\ClientPool; // Guzzle $asyncClient = new GuzzleClient($defer); // or using existing Guzzle client /** @var \GuzzleHttp\ClientInterface $client */ $asyncClient = new GuzzleClient($defer, $client); // Symfony HTTP Client $asyncClient = new SymfonyClient($defer); // or using existing Symfony client /** @var \Symfony\Contracts\HttpClient\HttpClientInterface $client */ $asyncClient = new SymfonyClient($defer, $client); $pool = new ClientPool($asyncClient);
发送请求
send
方法接受一个 PSR-7 请求的迭代器或接受 Psr\Http\Client\ClientInterface
实例的闭包/可调用类。
use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; // Using array $responses = $pool->send([ $psr7Request, fn (ClientInterface $client): ResponseInterface => $client->sendRequest($psr7Request), ]); var_dump($responses[0]); var_dump($responses[1]); // Using generator when you have an indeterminate amount of requests you wish to send $requests = static function (int $total) { for ($i = 0; $i < $total; $i++) { yield $psr7Request; } } $responses = $pool->send($requests(100));
获取响应
如您从上面的示例中看到,每个响应实例都可以通过索引访问。但是,响应顺序没有保证。如果您愿意,您可以为请求分配名称,以便轻松跟踪已发送的特定请求。这允许您通过其分配的名称访问相应的响应。
use Psr\Http\Client\ClientInterface; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; $responses = $pool->send([ 'first' => $psr7Request, 'second' => fn (ClientInterface $client): ResponseInterface => $client->sendRequest($psr7Request), ]); // Or using generator $requests = function (): \Generator { yield 'first' => $psr7Request; yield 'second' => fn (ClientInterface $client): ResponseInterface => $client->sendRequest($psr7Request); }; $responses = $pool->send($requests()); var_dump($responses['first']); var_dump($responses['second']);
并发限制
发送过多的请求可能会占用您这边的所有资源,或者如果远程端看到来自您这边的请求数量不合理,甚至可能会被禁用。
因此,通常建议将发送侧的并发限制在合理的值。通常使用相当小的限制,因为一次做超过十几件事可能会很容易压倒接收方。
您可以使用 concurrent
方法设置并发发送的最大请求数。默认值为 25
。
$response = $pool ->concurrent(10) // Process up to 10 requests concurrently ->send($requests);
超过并发限制的额外请求将自动入队,直到其中一个待处理请求完成。
测试
composer test
更新日志
请参阅 CHANGELOG 了解最近发生了什么更改。
贡献
请参阅 CONTRIBUTING 和 CODE_OF_CONDUCT 以获取详细信息。
安全性
如果您发现任何安全相关的问题,请发送电子邮件至 contact@lynh.me,而不是使用问题跟踪器。
致谢
许可证
MIT 许可证 (MIT)。请参阅 许可证文件 以获取更多信息。