节流websocket连接的首选方法是什么?

时间:2012-09-04 14:24:29

标签: python websocket eventlet

我有一个网络应用程序,我将模型更改流式传输到chrome客户端的主干集合。根据更新的类型和正在查看的内容,有一些主干视图可能会也可能不会呈现页面的某些部分。例如,对模型的某些更改会导致重新呈现集合的视图,并且可能会或可能不会为正在更新的模型打开详细信息面板视图。这些模型更改可以非常快速地发生,因为服务器端工作流程涉及对模型进行非常详细和快速的更改。

问题在于:在向客户端发送消息时,我在Web服务器的进程中收到了大量的errno 32管道损坏消息,尽管websocket连接仍在运行且其readyState仍为1(OPEN) )。

我怀疑正在发生的事情是,在下一条消息进入时,各种视图尚未在onmessage回调中完成呈现。在stdout中获得这些回溯后,websocket连接仍然可以正常工作用户界面仍将更新。

如果我将eventlet.sleep(0.02)放入从消息队列读取模型更改的循环中并将它们发送到websocket上,那么破坏的管道消息就会消失,但这不是一个真正的解决方案,而且感觉就像一个讨厌的黑客。

有没有人遇到类似的问题,websocket的onmessage函数试图做太多的工作而且在下一条消息进来时仍然很忙?有人有解决方案吗?

1 个答案:

答案 0 :(得分:0)

我认为最有效的方法是客户端应用告诉服务器他们正在显示什么。服务器会跟踪此情况并仅将更改发送到当前查看的对象,仅发送给相关客户端。

执行此操作的方法是使用“Who Watch What”项目列表。 项目以两种方式编制索引。从客户端ID和每个数据对象中的isVievedBy链表(我知道它看起来不干净,不能将它与数据混合,但它非常有效)。 您还需要为每个数据对象提供lastupdate时间戳。

当客户端更改视图时,它会向服务器发送“我正在查看此消息,我有版本-timestamp-”消息。服务器检查时间戳并在需要时发回对象。它还删除过时的“Who Watch What”(通过客户端ID访问它们)项目并创建新项目。

更新数据对象时,循环访问此对象的isVievedBy链表,以了解应更新哪个客户端。将它放在每个客户端的消息缓冲区中并手动刷新这些缓冲区(如果您同时更新多个项目,它将发送一条大消息)。

这是很多工作,但你的应用程序将是高效的,并且优雅地扩展,即使有很多对象和很多客户端。它只发送有用的消息,并且不太可能会有太多消息。

对于onMessage问题,我会将数据存储在队列中并异步处理它们。