过多的SSE连接导致网页卡顿

5 投票
3 回答
1993 浏览
提问于 2025-04-17 15:10

是什么限制了SSE(服务器发送事件)连接的数量?

我在做一个项目,使用的是django、gunicorn和django-sse。

我的项目在限制页面上的SSE连接数量时运行得很好(5个连接正常,6个连接就卡住了)。这不是个大问题,因为我使用了分页,可以限制每页的连接数。但我更希望能够随意连接更多。

我想问的是:是连接数量让它变慢,还是传输的数据量太大?

我觉得第一个问题可以通过让多个连接共享一个连接来解决,但第二个问题可能会让我受到更多限制。

有没有人能给点建议?

编辑:

客户端的JS SSE代码:

function event(url, resource_name, yes, no, audio_in, audio_out, current_draw){
    /**
     * Listens for events posted by the server
     * 
     * Useful site for understanding Server Sent Events:
     *    http://www.w3.org/TR/eventsource/
     */
    var source = new EventSource(url);
    source.addEventListener("message", function(e) {
        resetTime(resource_name);
        data = updateStatus(e.data, yes, no, audio_in, audio_out, current_draw);
        document.getElementById(resource_name+"-in").src = data.audio_in_src
        document.getElementById(resource_name+"-in").alt = data.audio_in_alt
        document.getElementById(resource_name+"-out").src = data.audio_out_src
        document.getElementById(resource_name+"-out").alt = data.audio_out_alt
        document.getElementById(resource_name+"-current").innerHTML = data.current_draw + " A"
    });
}

在views.py中:

class ServerSentEvent(RedisQueueView):

    def get_redis_channel(self):
        """
        Overrides the RedisQueueView method to select the channel to listen to
        """
        return self.kwargs["resource_name"]

在urls.py中:

urlpatterns = patterns('',
                       url(r'^$',
                           views.Resources_page.as_view(),
                           name='resources_page'),
                       url(r'^(?P<resource_name>\w+)/$',
                           views.StatusPage.as_view(),
                           name='status_page'),
                       url(r'^(?P<resource_name>\w+)/sse/$',
                           views.ServerSentEvent.as_view(),
                           name='sse'),)

3 个回答

0

浏览器通常会限制与同一个服务器的连接数量。你可以在浏览器的设置中查看这个限制,比如在Firefox浏览器中,你可以在地址栏输入“about:config”来查看相关设置。在那里,你会看到一个类似于 { network.http.speculative-parallel-limit 6 } 的设置,意思是最多可以同时连接6个。你当然可以把这个数字改得更大,然后进行测试。

所以,这个问题并不是出在服务器那边。

0

如果你在使用gunicorn的sync工作进程(这是默认设置),那么你能同时连接到服务器的数量就和你有多少个工作进程一样。

sync工作进程是为那些需要大量计算的任务设计的,所以建议使用2N + 1个工作进程(N是你电脑上可用的核心数量)。如果你的SSE接口在逻辑上等同于这个...

while True:
    msg = "foo"
    yield msg
    sleep(1)

...那么你就有一个I/O密集型的视图。无论你给那段代码多少CPU时间,它都是设计成不会结束的。如果你使用django_sse项目,那么这几乎就是你的SSE视图在做的事情

解决办法是为gunicorn使用异步工作进程类。安装gevent,然后在启动gunicorn时加上--worker-class=gevent选项,这样你就可以进入一个异步的理想状态了。

1

我遇到过完全一样的问题。我原本以为我在用gevent作为工作者,但连接数却只有大约6个。

解决办法其实很简单。这是浏览器的限制。我把这个写下来,方便下一个遇到这个问题的人看到。

在Firefox浏览器中,有一个设置项在about:config里,叫做 network.http.max-persistent-connections-per-server,这个设置控制着连接的数量。所以在我的情况下,解决办法就是把这个数字从默认的6增加,或者换几个浏览器来用。

撰写回答