У меня есть торговый бот, который работает синхронно в l oop:
- curl для данных книги заказов,
- trade - отправить / отменить предложение
- continue
Этот подход работает нормально, но некоторые каналы книги заказов не обновляются, если вы запрашиваете их по обычному HTTPS. Эти стороны предлагают каналы Websocket. Теперь это добавляет сложности, потому что с одной стороны мне нужно обрабатывать сообщения Websocket. С другой стороны, я запускаю бота в l oop.
Я пробовал подход с событием l oop. Fetcher
обновляется сообщениями веб-сокета, OfferManager
торгуется по методу run
:
<?php
$fetcher = new FetchOffersExchangeWebsocket();
$manager = new SellOnlyOfferManager($fetcher);
$loop = \React\EventLoop\Factory::create();
$reactConnector = new \React\Socket\Connector($loop);
$connector = new \Ratchet\Client\Connector($loop, $reactConnector);
$connector('wss://api.trading.net/websocket')
->then(function(Ratchet\Client\WebSocket $conn) use($fetcher, $manager) {
$subscribe = [
"action" => "subscribe",
"path" => "orderbook"
];
$conn->send(json_encode($subscribe));
$conn->on('message', function(\Ratchet\RFC6455\Messaging\MessageInterface $msg) use ($conn, $fetcher, $manager) {
$message = json_decode((string) $msg, true);
$fetcher->update($message);
$manager->run();
});
}, function(\Exception $e) use ($loop) {
echo "Could not connect: {$e->getMessage()}\n";
$loop->stop();
});
$loop->run();
Первая очевидная проблема, которая возникла, заключается в том, что OfferManager->run()
блокирует выполнение обновления веб-сокета. В этом случае, если есть много обновлений веб-сокетов, над которыми нужно действовать, мой бот отстает, поскольку он застрял на некоторых старых сообщениях, которые выполняют run()
, и все это требует времени.
Я не уверен, как лучше всего подойти к этому , но мне кажется, что мне нужно обновить Websocket в одном потоке и у меня есть способ поделиться конечным состоянием (снимком книги заказов) с потоком, в котором работает бот l oop.
Is есть ли какой-нибудь generi c подход к этой проблеме?
Есть ли чистый способ нанять PHP для решения этой проблемы? Кажется, я мог бы запустить бота на переднем плане и запустить обновление Websocket
асинхронно, используя: https://www.php.net/manual/en/intro.parallel.php, а затем используя Channel
, я мог бы передать эти данные обратно на передний план.
Любые подсказки приветствуются.
РЕДАКТИРОВАТЬ: Я не уверен, как правильно подойти к этому, но помогло использование неблокирующего потока для получения данных Websocket. stream_set_blocking($stream, false)
. Если в потоке нет данных, он возвращает пустую строку, но не блокирует выполнение. Затем я могу запустить fread
в потоке до тех пор, пока не будет данных, а затем я могу запустить свой: $manager->run()
. После его завершения я догоняю все сообщения, ожидающие обработки в буфере. Это не блокирует выполнение l oop.