Posted on 2013-03-08 20:18:01 tornado
摘要:使用tornado的异步http调用时候,在继续RequestHandler的子类中,可以重载on_connection_close方法。 此方法在对端连接关闭,或者在socket上读写错误的时候被调用,可以让服务器做一些清理。
阅读全文Posted on 2013-03-07 19:03:17 network
最近在折腾一个长连接HTTP服务器的时候,积累了一些经验,下面总结出来:
最好使用支持HTTP/1.1的服务器,HTTP/1.1默认支持keep-alive,不需要像HTTP/1.0那样检测Connection: keep-alive.
浏览器的刷新也会断开长连接,如果在服务端有一些判断,要注意发生重复的可能。
在用户关闭浏览器的标签的时候,如果有多个页面和服务器保持长连接,服务器应检测对应的页面,并做清理。
将长连接服务器位于反向代理之后,应在反向代理服务器上设置保持keep-alive,如nginx。 这样可显著减少后端upstream服务器的压力。
检测用户刷新页面,如果刷新应询问用户是否真的刷新。这样可以减少一些误判断。 如WEBQQ在检测到用户刷新时,对应的动作是重新登录。 这样做是很好,可以预防用户在当前页面重复触发一些业务逻辑。
如因为业务需要将长连接和会话绑定(很多WEB IM都这样做),应注意清理服务端保持的长连接。 发送完消息,就应该删除这个长连接。因为浏览器ajax请求还会立即请求的。
Posted on 2013-03-06 19:49:00 os
Nginx upstream目前只有短连接,通过HTTP/1.0向后端发起连接,并把请求的”Connection” header设为”close”。Nginx与前端的连接默认为长连接,一个用户跟Nginx建立连接之后,通过这个长连接发送多个请求。如果Nginx只是作为reverse proxy的话,可能一个用户连接就需要多个向后端的短连接。如果后端的服务器(源站或是缓存服务器)处理并发连接能力不强的话(比如单进程的squid),就可能导致瓶颈的出现。
从nginx 1.1.4 开始有了原生的ngx_http_upstream_keepalive 模块 和”proxy_http_version” fastcgi_keep_conn” 等指令 ,所以后端的keepalive也在nginx 1.2.0成为现实。
HTTP 1.0实现长连接需要设置请求头部Connection: keep-alive。 但是在HTTP 1.1 中已经不需要了。 所以在nginx中这样配置:
upstream http_backend {
server 127.0.0.1:8080;
keepalive 16;
}
server {
...
location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
Posted on 2013-03-06 15:16:21 tornado
在tornado中是根据send buffer中的内容计算etag的,而这样对于一些只判断逻辑的页面会有问题。
计算etag的代码如下:
def compute_etag(self):
"""Computes the etag header to be used for this request.
May be overridden to provide custom etag implementations,
or may return None to disable tornado's default etag support.
"""
hasher = hashlib.sha1()
for part in self._write_buffer:
hasher.update(part)
return '"%s"' % hasher.hexdigest()
可以很清楚的看到,是根据self._writer_buffer中的内容计算etag,然后返回。
但是如果遇到下面的代码会出现问题:
def post(self):
username = self.get_argument("username")
if not redis.UserManager.is_user_exists(username):
self.set_secure_cookie("user", username)
self.redirect("/room", status=301)
return
else:
self.render("login.html", user_exists=True)
这段代码中,返回的内容永远不会有变化。 所以客户端判断返回为304,导致出现问题。 解决方法是禁用etag。解决方法很简单,只要重载compute_etag方法,并返回None即可。 并且建议,对于所有动态页面,不用计算etag的方法,这样可以让客户端永远获取最新的内容。 如果真的要客户端缓存页面,可以用Cache-Control,设置有效期,这样比较合理。