过多的SSE连接导致网页卡顿
是什么限制了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 个回答
浏览器通常会限制与同一个服务器的连接数量。你可以在浏览器的设置中查看这个限制,比如在Firefox浏览器中,你可以在地址栏输入“about:config”来查看相关设置。在那里,你会看到一个类似于 { network.http.speculative-parallel-limit 6 } 的设置,意思是最多可以同时连接6个。你当然可以把这个数字改得更大,然后进行测试。
所以,这个问题并不是出在服务器那边。
如果你在使用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
选项,这样你就可以进入一个异步的理想状态了。
我遇到过完全一样的问题。我原本以为我在用gevent作为工作者,但连接数却只有大约6个。
解决办法其实很简单。这是浏览器的限制。我把这个写下来,方便下一个遇到这个问题的人看到。
在Firefox浏览器中,有一个设置项在about:config里,叫做 network.http.max-persistent-connections-per-server
,这个设置控制着连接的数量。所以在我的情况下,解决办法就是把这个数字从默认的6增加,或者换几个浏览器来用。