【问题标题】:Can websockets "lag" when a lot of messages are received?当收到大量消息时,websockets 会“滞后”吗?
【发布时间】:2020-12-10 18:01:18
【问题描述】:

我正在尝试使用 asyncio 和 websocket 创建一个脚本,该脚本应该连接到 4-5 个加密货币交易所 websocket,并从这些交易所实时接收交易。我的代码有效,而且非常简单,如下所示:

import asyncio
import websockets
import json

subscriptions = ['btcusdt@trade', 'ethusdt@trade', 'bchusdt@trade', 'xrpusdt@trade', 'eosusdt@trade', 'ltcusdt@trade', 'trxusdt@trade', 'etcusdt@trade', 'linkusdt@trade', 'xlmusdt@trade', 'adausdt@trade', 'xmrusdt@trade', 'dashusdt@trade', 'zecusdt@trade', 'xtzusdt@trade', 'bnbusdt@trade', 'atomusdt@trade', 'ontusdt@trade', 'iotausdt@trade', 'batusdt@trade', 'vetusdt@trade', 'neousdt@trade', 'qtumusdt@trade', 'iostusdt@trade', 'thetausdt@trade', 'algousdt@trade', 'zilusdt@trade', 'kncusdt@trade', 'zrxusdt@trade', 'compusdt@trade', 'omgusdt@trade', 'dogeusdt@trade', 'sxpusdt@trade', 'kavausdt@trade', 'bandusdt@trade', 'rlcusdt@trade', 'wavesusdt@trade', 'mkrusdt@trade', 'snxusdt@trade', 'dotusdt@trade', 'defiusdt@trade', 'yfiusdt@trade', 'balusdt@trade', 'crvusdt@trade', 'trbusdt@trade', 'yfiiusdt@trade', 'runeusdt@trade', 'sushiusdt@trade', 'srmusdt@trade', 'bzrxusdt@trade', 'egldusdt@trade', 'solusdt@trade', 'icxusdt@trade', 'storjusdt@trade', 'blzusdt@trade', 'uniusdt@trade', 'avaxusdt@trade', 'ftmusdt@trade', 'hntusdt@trade', 'enjusdt@trade', 'flmusdt@trade', 'tomousdt@trade', 'renusdt@trade', 'ksmusdt@trade', 'nearusdt@trade', 'aaveusdt@trade', 'filusdt@trade', 'rsrusdt@trade', 'lrcusdt@trade', 'maticusdt@trade', 'oceanusdt@trade', 'cvcusdt@trade', 'belusdt@trade', 'ctkusdt@trade', 'axsusdt@trade', 'alphausdt@trade', 'zenusdt@trade', 'sklusdt@trade']

async def connect():
    while True:
        async with websockets.client.connect('wss://fstream.binance.com/ws/trade') as ws:
        
                tradeStr = {"method": "SUBSCRIBE", "params": subscriptions, 'id': 1}
                await ws.send(json.dumps(tradeStr))

                while True:
                    try:
                        msg = await asyncio.wait_for(ws.recv(), 5)
                        message = json.loads(msg)

                        try:    
                            print(message)
                        except Exception as e:
                            print(e)

                    except asyncio.TimeoutError:
                        break


asyncio.get_event_loop().run_until_complete(connect())

在上面的示例中,我正在连接到 Binance,并且我正在接收所有可用市场的交易。我这样做是为了一次进行更多的交流,但只要我每秒收到很多消息,问题也会发生。

每条消息都像这样{"rate": "xx", "market": "xx", "amount": "xx", "side": "xx"},非常小。

我注意到的一个大问题是,在脚本运行一段时间后,我开始收到较少的消息,很多消息会在很多秒后出现,而我什至没有收到很多其他消息,好像他们迷路了,或者好像连接被冻结了。

现在,我知道这不是一个非常具体的问题,但这里可能是什么问题?

当 websockets 每秒接收大量消息时,是否有可能出现此类问题?我试图从我的本地和 vps 测试这个系统,在这两种情况下我都遇到了同样的问题。这可能是资源问题吗?或者它最有可能与服务器有关,而不是我的客户端?我试图尽可能具体,如果需要,我可以更详细。 我读到websockets 将收到的消息存储在缓冲区中。问题是否可能是缓冲区被填满? 任何形式的建议都值得赞赏!

【问题讨论】:

  • 您能提供更多信息吗?所示代码不是minimal reproducible example,它与您的描述不太匹配(没有并发),而且它似乎没有做任何有用的事情(只是打印数据)。确定问题出在asyncio/websockets 而不是您的程序累积数据?
  • 您好,我将代码编辑为完全可重现;它只打印数据,因为现在它只需要这样做,问题不在于我需要对这些数据做什么,而在于一段时间后它将开始冻结,发送更少的数据和滞后的问题,如果你运行你会注意到同样的
  • 我并不是说问题出在 asyncio 或 websockets 上,这意味着它们存在错误,我试图了解这个系统的瓶颈在哪里以及如何解决这个问题。问题很可能与我收到大量消息有关,如果我理解正确,缓冲区将满,这是一个假设
  • 如果您在 Linux 上使用许多有用的监控工具,您可以使用 nethogs、top 或 htop 等工具检查您的网络 IO、内存或 CPU 是否饱和。一旦你排除了其中一种饱和,你就可以尝试更深入地挖掘并开始调查 Binance 是否会限制你的速率或诸如此类......
  • 我刚刚运行了你的代码,到目前为止我没有任何问题,至少运行了大约 10 分钟。带宽使用率非常低(平均约为 25Kbps),而且 cpu 似乎也很安静(我的旧 2013 macbook pro 上的 cpu 使用率

标签: python python-3.x websocket cryptocurrency


【解决方案1】:

根据您的解释和我的经验,这似乎与资源管理有关,是的,如果您每秒收到大量消息,WebSockets 会受到影响,是的,这会导致您的服务器出现问题。为什么?因为缓冲区当然是有限的,而且可用于同时处理所有这些消息的内存量,正如他们在WebSocket 库(version 8.1) 的官方文档中提到的那样,我认为你的问题是你是opening a lot number of connections at the same time and this causes memory exhaustion 当然这些取决于消息的大小和服务器的资源,这可以很容易地测试你可以用2个VPS尝试它,如果2个服务器有不同的时间运行到不同数量的资源该状态绝对是资源之一(我认为这应该是预期的结果,应该首先遇到更少的资源,并且资源意味着内存)。以下是WebSockets 库的官方文档的一些链接,其中引用了由内存引起的这些问题以及优化内存使用的方法。希望对你有所帮助?。

Memory Usage Optimizations

【讨论】:

  • 非常感谢您的回答;不过,就代码而言,我能做些什么来改进甚至部分解决这个问题?或者是获得更好硬件的唯一解决方案?
  • 我不认为这里的问题是代码库,可以做一些改进的事情,例如,从架构的角度来看,比如使用微服务以异步方式处理这些消息,然后得到一个通过 webhook(或类似的东西)通知您不需要“等待”响应,现在以这种方式思考上面代码中唯一可以增加复杂性(执行时间)的是等待或你的例子末尾的函数所以对我来说似乎不是代码库@JayK23
  • 如果答案对你来说是正确的请标记它?,希望上面的评论有帮助! @JayK23
  • 你可以使用Tornado,Tornado 是一个 Python Web 框架和异步网络库,使用非阻塞网络 I/O,Tornado 可以扩展到数万个打开的连接,非常适合长期使用轮询、WebSocket 和其他需要与每个用户建立长期连接的应用程序。
猜你喜欢
  • 2023-01-15
  • 2017-03-28
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 2020-08-30
  • 2019-09-14
  • 1970-01-01
  • 2011-05-19
相关资源
最近更新 更多