本地的Python HTTP服务器很慢
我在创建一个非常简单的Python HTTP服务器时遇到了一些性能问题。主要的问题是,性能会根据我使用的客户端不同而有所变化,而服务器和所有客户端都是在本地机器上运行的。例如,从一个Python脚本发出的GET请求(urllib2.urlopen('http://localhost/').read())需要花费超过一秒钟才能完成,这在服务器没有负载的情况下看起来有点慢。而从Excel使用MSXML2.ServerXMLHTTP发出的GET请求也感觉很慢。不过,从Google Chrome或者使用R的curl插件RCurl请求数据时,响应几乎是瞬间的,这正是我所期待的。
让我更困惑的是,当我在工作电脑上时,任何客户端都没有遇到性能问题(性能问题出现在我家里的电脑上)。这两台电脑都运行Python 2.6,不过工作电脑是Windows XP,而不是7。
下面是我非常简单的服务器示例,它对于任何GET请求都会返回“Hello world”。
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
print("Just received a GET request")
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write('Hello world')
return
def log_request(self, code=None, size=None):
print('Request')
def log_message(self, format, *args):
print('Message')
if __name__ == "__main__":
try:
server = HTTPServer(('localhost', 80), MyHandler)
print('Started http server')
server.serve_forever()
except KeyboardInterrupt:
print('^C received, shutting down server')
server.socket.close()
注意,在MyHandler中,我重写了log_request()和log_message()这两个函数。这样做的原因是我看到有人说,这些函数执行的完全合格域名查找可能会导致服务器变慢。不幸的是,把它们设置为只打印一个静态消息并没有解决我的问题。
另外,请注意我在MyHandler的do_GET()例程的第一行放了一个print()语句。慢的情况发生在这个消息打印之前,这意味着后面的内容并没有导致延迟。
3 个回答
把localhost换成127.0.0.1可以解决这个问题哦 :)
请求处理程序会进行反向名称查找,以便在日志中显示客户端的名称。我的Windows 7系统首先进行了一次DNS查找,但没有成功,接着又进行了两次NetBIOS名称查询,每次都超时了2秒,总共延迟了4秒!!
可以看看这个链接:https://bugs.python.org/issue6085
对我有效的另一个解决办法是,在我的请求处理程序中重写BaseHTTPRequestHandler.address_string()
,用一个不进行名称查找的版本。
def address_string(self):
host, port = self.client_address[:2]
#return socket.getfqdn(host)
return host
Philippe
这听起来不像是代码的问题。一个很好的方法来排查HTTP服务器的问题,就是用telnet连接到它的80端口。然后你可以输入类似下面的内容:
GET /index.html HTTP/1.1
host: www.blah.com
<enter> <enter>
然后观察服务器的回应。看看用这种方法是否会有延迟。
你可能还想关闭任何防火墙,看看它们是否导致了速度变慢。
试试把127.0.0.1换成localhost。如果这样解决了问题,那就说明可能是FQDN查找导致的。