Как работает параллель Amphp?

Я читал об ampphp, и у меня были сомнения относительно параллельного

Пример кода:

<?php

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

$client = new Amp\Artax\DefaultClient;
$promises = [];

$urls = [
    "http://google.com.br",
    "http://facebook.com.br",
    "http://xat.com/",
    "http://kobra.ninja/",
    "http://wikipedia.com",
    "http://manualdomundo.com.br",
    "http://globo.com",
    "http://gmail.com"
];

foreach ($urls as $url) {
    $promises[$url] = Amp\call(function () use ($client, $url) {
        // "yield" inside a coroutine awaits the resolution of the promise
        // returned from Client::request(). The generator is then continued.
        $response = yield $client->request($url);

        // Same for the body here. Yielding an Amp\ByteStream\Message
        // buffers the entire message.
        $body = yield $response->getBody();
        echo $url;
        return $url;
    });
}

$responses = Amp\Promise\wait(Amp\Promise\all($promises));

Этот код выполняет все завитки или ждет, пока 1 выполнит другой?


person kobra101    schedule 12.01.2020    source источник


Ответы (2)


Это использует функциональность stream_select. Он не работает параллельно обычным способом, о котором вы думаете. Он работает, регистрируя обратный вызов, который будет вызываться, когда потоки доступны для чтения/записи, а затем возвращается, когда выполняется конкретное обещание, которого вы ждете. Все другие промисы, которые разрешаются за это время, завершаются и кэшируются в соответствующих промисах, ожидая, пока вы развернете значение с помощью yield или Promise::onResolve. Цикл событий Amp — это то, что управляет несколькими сокетами и обрабатывает параллелизм для вас.

Если вам нужен базовый пример того, как это работает, я разместил на GitHub образец проекта, который состоит из двух классов, но основан на Curl вместо stream_select: https://github.com/kwhat/requestful

Все, что требуется для настроить интерфейс обещания. Вся магия здесь основана на двух обратных вызовах, переданных конструктору, а также на оболочках обратных вызовов then/cancel.

Метод sendRequestAsync — это то, как параллельный Curl создаются запросы. Все волшебство происходит в обратном вызове для wait() для любого промиса, который вызывает анонимная функция, которая стажером вызывает метод tick в цикле. Этот метод tick() разрешает все обещания, независимо от того, какое из них вы вызываете ожиданием.

person Alex Barker    schedule 12.01.2020
comment
Нет, он не использует curl_multi, он вообще не использует Curl. Без расширений он использует stream_select() и неблокирующий ввод-вывод и реализует протокол HTTP и потоки на основе stream_* функций PHP. - person kelunik; 27.04.2020

Как видно из кодовой базы Amp, он будет выполнять все ваши запросы внутри одного и того же цикла обработки событий.

Учитывая, что ваши запросы обрабатываются (yield $client->request($url)) и обрабатываются внутри одного и того же цикла обработки событий, они отправляются одновременно.

Я рекомендую вам прочитать эту статью до конца, особенно раздел «Асинхронная разработка: как работает Amp framework». Я думаю, что это немного прояснит, как работает движок за кулисами.

Надеюсь, это было полезно. Ваше здоровье! :)

person Nawarian    schedule 17.01.2020
comment
Artax не основан на Curl, поэтому я отредактировал ваш ответ, чтобы исправить это. :-) - person kelunik; 27.04.2020