8

我们有一个非常复杂的 Django 应用程序,目前由 apache/mod_wsgi 提供服务,并部署在 AWS ELB 负载均衡器后面的多个 AWS EC2 实例上。客户端应用程序使用 AJAX 与服务器交互。他们还定期轮询服务器以检索通知和更新其状态。我们希望删除轮询并将其替换为“推送”,使用网络套接字。

因为任意实例处理来自客户端的 Web 套接字请求并保留这些 Web 套接字,并且因为我们希望将数据推送到可能不在为推送提供源数据的同一实例上的客户端,所以我们需要一种方法将数据路由到适当的实例,然后从该实例到适当的客户端 Web 套接字。

我们意识到 apache/mod_wsgi 不能很好地使用 web sockets,并计划用 nginx/gunicorn 替换这些组件并使用 gevent-websocket worker。但是,如果多个工作进程之一接收到来自客户端的建立 Web 套接字的请求,并且工作进程的生命周期由主 gunicorn 进程控制,则不清楚其他工作进程,或者实际上是非 gunicorn 进程如何可以将数据发送到这些 Web 套接字。

一个特定的情况是:发出 HTTP 请求的用户被定向到一个 EC2 实例(主机),并且期望的行为是将数据发送给在完全不同的实例中打开 Web 套接字的另一个用户。可以很容易地设想一个系统,其中运行在每个实例上的消息代理(例如rabbitmq)可以发送包含要通过网络套接字发送到连接到该实例的客户端的数据的消息。但是这些消息的处理程序如何访问在 gunicorn 的工作进程中接收到的 Web 套接字?创建 gevent-websocket 并提供给工作人员的高级 python web 套接字对象不能被腌制(它们是不支持腌制的实例方法),因此工作进程不能轻易地将它们共享给一些长时间运行的外部过程。

事实上,这个问题的根源在于,由客户端的 HTTP 请求发起并由 gunicorn 等服务器中的 WSGI 处理程序处理的 Web 套接字如何被外部进程访问?旨在处理 HTTP 请求的 gunicorn 工作进程会产生长时间运行的线程以挂在 Web 套接字上并支持处理来自其他进程的消息以将消息发送到已通过这些工作进程附加的 Web 套接字,这似乎并不正确过程。

谁能解释一下 Web 套接字和基于 WSGI 的 HTTP 请求处理程序如何在我描述的环境中相互作用?

谢谢。

4

2 回答 2

1

我认为你已经做出了正确的评估,即 mod_wsgi + websockets 是一个令人讨厌的组合。

您会发现所有 wsgi 工作人员都被 Web 套接字占用,并且尝试(大量)增加工作人员池的大小可能会因为内存使用和上下文切换而阻塞服务器。

如果您喜欢坚持使用同步 wsgi worker 架构(与 gevent、twisted、tornado 等实现的反应式方法相反),我建议您将 uWSGI 视为应用程序服务器。最近的版本可以以旧的方式处理一些 URL(即您现有的 django 视图仍然可以像以前一样工作),并将其他 url 路由到异步 websocket 处理程序。这对您来说可能是一条相对顺利的迁移路径。

于 2014-02-03T15:16:23.703 回答
0

旨在处理 HTTP 请求的 gunicorn 工作进程会产生长时间运行的线程以挂在 Web 套接字上并支持处理来自其他进程的消息以将消息发送到已通过这些工作进程附加的 Web 套接字,这似乎并不正确过程。

为什么不?毕竟,这是一个长期运行的连接。处理这种连接的长期线程似乎......对我来说绝对自然。

通常在这些事件的情况下,写入与读取是分开处理的。

当前正在处理 websocket 连接的工作人员将等待相关消息从消息传递服务器下来,然后将其传递给 websocket。

如果您愿意,还可以使用 gevent 的异步友好队列来处理代码内消息传递。

于 2013-03-08T04:48:52.343 回答