耗时异步请求不是真的异步吗?

编程入门 行业动态 更新时间:2024-10-27 03:40:00
本文介绍了耗时异步请求不是真的异步吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我们正在尝试使用guzzle进行并发异步请求.经过一些资源后,例如此和此,我们想出了一些下面共享的代码.但是,它没有按预期工作.

We are trying to do concurrent asynchronous requests using guzzle. After going through a few resources, like this and this, we came up with some code that is shared below. However it is not working as expected.

似乎Guzzle正在同步执行这些请求,而不是异步执行.

It looks like Guzzle is doing these request synchronously rather than async.

仅出于测试目的,我们点击了一个内部网址,该网址进行了5秒钟的睡眠.并发性为10时,我们希望所有10个请求最初都将排队并同时发送到服务器几乎,在那里它们将等待5秒钟,然后所有几乎这些将几乎同时完成.如此一来,耗时的客户端就会收到来自迭代器的10个新请求,依此类推.

Just for test purposes, we are hitting an internal url, which does a 5 second sleep. With a concurrency of 10 we expect that all 10 requests will initially be queued and send to the server almost simultaneously, where they will wait for 5 seconds, and will then almost all of those will finish nearly at the same time. Which would make the guzzle client to pick up 10 new requests from iterator and so on.

$iterator = function() { $index = 0; while (true) { $client = new Client(['timeout'=>20]); $url = 'localhost/wait/5' . $index++; $request = new Request('GET',$url, []); echo "Queuing $url @ " . (new Carbon())->format('Y-m-d H:i:s') . PHP_EOL; yield $client ->sendAsync($request) ->then(function(Response $response) use ($request) { return [$request, $response]; }); } }; $promise = \GuzzleHttp\Promise\each_limit( $iterator(), 10, /// concurrency, function($result, $index) { /** GuzzleHttp\Psr7\Request $request */ list($request, $response) = $result; echo (string) $request->getUri() . ' completed '.PHP_EOL; }, function(RequestException $reason, $index) { // left empty for brevity } ); $promise->wait();

实际结果

我们发现Guzzle在第一个请求完成之前从未提出第二个请求.等等.

Actual Results

We find that that Guzzle never made a second request until the first one is finished. and so on.

Queuing localhost/wait/5/1 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/2 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/3 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/4 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/5 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/6 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/7 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/8 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/9 @ 2017-09-01 17:15:28 Queuing localhost/wait/5/10 @ 2017-09-01 17:15:28 localhost/wait/5/1 completed Queuing localhost/wait/5/11 @ 2017-09-01 17:15:34 localhost/wait/5/2 completed Queuing localhost/wait/5/12 @ 2017-09-01 17:15:39 localhost/wait/5/3 completed Queuing localhost/wait/5/13 @ 2017-09-01 17:15:45 localhost/wait/5/4 completed Queuing localhost/wait/5/14 @ 2017-09-01 17:15:50

操作系统/版本信息

  • Ubuntu
  • PHP/7.1.3
  • GuzzleHttp/6.2.1
  • curl/7.47.0

问题可能出在\ GuzzleHttp \ Promise \ each_limit ..可能无法快速启动或解决承诺.我们可能有可能不得不把它诱骗到外部tick.

The issue could be with \GuzzleHttp\Promise\each_limit .. which perhaps does not initiates or resolves the promise fast enough. It may be possible that we have to trick that into ticking externally.

推荐答案

在示例代码中,您正在为要发出的每个请求创建一个新的GuzzleHttp\Client实例.这似乎并不重要,但是,在实例化GuzzleHttp\Client期间,它将设置默认的处理程序(如果未提供). (然后,该值将传递给通过客户端发送的任何请求,除非被覆盖.)

In the example code, you're creating a new GuzzleHttp\Client instance for every request you want to make. This might not seem important, however, during instantiation of GuzzleHttp\Client it will set a default handler if none is provided. (This value is then passed down to any request being sent through the Client, unless it is overridden.)

注意:它从此<确定<函数.不过,很可能最终会默认为curl_mutli_exec.

Note: It determines the best handler to use from this function. Though, it'll most likely end up defaulting to curl_mutli_exec.

这有什么重要性?底层处理程序负责同时跟踪和执行多个请求.通过每次创建一个新的处理程序,您的所有请求都不会被正确地分组并一起运行.有关此内容的更多信息,请细读 curl_multi_exec文档.

What's the importance of this? It's the underlying handler that is responsible for tracking and executing multiple requests at the same time. By creating a new handler every time, none of your requests are properly being grouped up and ran together. For some more insight into this take a gander into the curl_multi_exec docs.

因此,您有两种处理方式:

So, you kind of have two ways of dealing with this:

通过客户端到达迭代器:

Pass through the client through to the iterator:

$client = new GuzzleHttp\Client(['timeout' => 20]); $iterator = function () use ($client) { $index = 0; while (true) { if ($index === 10) { break; } $url = 'localhost/wait/5/' . $index++; $request = new Request('GET', $url, []); echo "Queuing $url @ " . (new Carbon())->format('Y-m-d H:i:s') . PHP_EOL; yield $client ->sendAsync($request) ->then(function (Response $response) use ($request) { return [$request, $response]; }); } }; $promise = \GuzzleHttp\Promise\each_limit( $iterator(), 10, /// concurrency, function ($result, $index) { /** @var GuzzleHttp\Psr7\Request $request */ list($request, $response) = $result; echo (string)$request->getUri() . ' completed ' . PHP_EOL; } ); $promise->wait();

或在其他位置创建处理程序并将其传递给客户端:(尽管我不确定为什么要这样做,但是它在那里!)

or create the handler elsewhere and pass it to the client: (Though I'm not sure why you'd do this, but it's there!)

$handler = \GuzzleHttp\HandlerStack::create(); $iterator = function () use ($handler) { $index = 0; while (true) { if ($index === 10) { break; } $client = new Client(['timeout' => 20, 'handler' => $handler]) $url = 'localhost/wait/5/' . $index++; $request = new Request('GET', $url, []); echo "Queuing $url @ " . (new Carbon())->format('Y-m-d H:i:s') . PHP_EOL; yield $client ->sendAsync($request) ->then(function (Response $response) use ($request) { return [$request, $response]; }); } }; $promise = \GuzzleHttp\Promise\each_limit( $iterator(), 10, /// concurrency, function ($result, $index) { /** @var GuzzleHttp\Psr7\Request $request */ list($request, $response) = $result; echo (string)$request->getUri() . ' completed ' . PHP_EOL; } ); $promise->wait();

更多推荐

耗时异步请求不是真的异步吗?

本文发布于:2023-11-11 17:48:37,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1579141.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:不是真的

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!