对 Amazon Firehose 的异步请求

Asynchronous request to Amazon Firehose

是否可以异步向 AWS 发送请求?在真正意义上。

如果我尝试以以下方式发送消息,则消息未送达:

      $firehose = new FirehoseClient($args);
      /** @var Promise\Promise $promise */
      $promise = $firehose->putRecordAsync($record);
      $promise->then(function ($result) {
          echo 'test';
      });

但是当我在脚本末尾添加时:

$promise->wait()

它可以工作,但是是同步的。有什么办法让它异步吗?

我也尝试过使用不同的处理程序:

    $curl = new CurlMultiHandler();
    $handler = HandlerStack::create($curl);
    $args = [
        'http_handler' => $handler,
        'region' => '#REGION#',
        'version' => 'latest',
        'credentials' => $credentials,
        'debug' => true
    ];
    $firehose = new FirehoseClient($args);

    while (!Promise\is_settled($promise)) {
        $curl->tick();
    }

基本上可以,但总是处于同步模式。我需要的是向 AWS 发送请求而不是等待答案。

我在 PHP 中没有使用异步代码,但我在 Python 中使用过这些东西。

从一般的理解来看,您无法从同步代码包围的单个异步请求中获得任何好处。您应该在完全异步的环境中工作(即您需要某种外部事件循环)。 ReactPHP 看起来就是其中之一。

此外,您可以同时发出多个 API 请求并同时等待所有请求。就像这个例子 http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/promises.html#executing-commands-concurrently 它会比连续进行多个同步调用更快。

希望对您有所帮助。

您的问题的最佳解决方案是使用事件循环实现,例如 ReactPHP。

不幸的是,Guzzle(更好的说法是 cURL 本身)不兼容开箱即用的事件循环。

就我个人而言,我通过实施 bridge to run Guzzle queries event-loop-friendly. Please, take a look at the examples.

解决了同样的问题

因此代码可能如下所示:

run(function ($loop) use ($genFn) {
    $httpHandler = new CurlMultiHandler($loop);
    $stack = HandlerStack::create($httpHandler);

    $httpClient = new Client([
        'handler' => $stack,
    ]);

    $promise = $httpClient->getAsync('https://google.com')->then(
        function ($result) { echo 'Query completed!'; },
        function ($reason) { echo 'Query failed.'; }
    );

    /*
     * The promise isn't completed yet, but the event loop will take care of it.
     * We don't need to call Promise::wait()!
     */
});