我有一个现有的交易机器人,它可以在循环中同步运行:
这种方法很好用,但是如果您通过常规HTTPS查询某些订单提要,则它们不是最新的。这些团体提供Websocket提要。 现在这增加了一些复杂性,因为一方面需要处理Websocket消息。另一方面,我正在循环中运行一个机器人。
我已经尝试了事件循环方法。 Fetcher
得到了websocket消息的更新,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()
阻止了websocket更新的执行。在这种情况下,如果要执行许多websocket更新,那么我的机器人就落后了,因为它滞留在一些执行run()
的较旧消息上,并且都需要时间。
我不确定如何最好地实现它,但是在我看来,我需要在一个线程中更新Websocket,并有办法与bot循环所在的线程共享最终状态(订单簿快照)运行。
有没有通用的方法可以解决这个问题?
是否有租用PHP的干净方法来解决此问题?
看来我可以在前台运行该bot并以某种方式异步运行Websocket
更新:https://www.php.net/manual/en/intro.parallel.php,然后使用Channel
我可以将该数据传递回前台。
任何提示表示赞赏。
编辑:我不确定如何很好地处理它,但是有用的是使用非阻塞流来获取Websocket数据。 stream_set_blocking($stream, false)
。
如果流中没有数据,它将返回空字符串,但不会阻止执行。然后,我可以在流上运行fread
直到没有数据,然后可以运行我的$manager->run()
。完成后,我将追赶缓冲区中正在等待处理的所有消息。
这不会阻塞执行循环。