【发布时间】:2014-07-07 15:15:33
【问题描述】:
我有一个带有 tornado 框架的 python http 服务器。多次请求后,它变得不可用。在浏览器页面中也不可用。大约 20 秒不活动后,它又开始工作了。
100,000 个查询包含大约 10 个异常。在此负载下,服务器进程消耗大约 30% 的 CPU。
为什么服务器不可用?
服务器:
start_port = 4400
workers = 1
class MainHandler(tornado.web.RequestHandler):
def get(self):
data = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(1000))
self.write(data)
def server_process(port):
application = tornado.web.Application([
(r"/", MainHandler),
])
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == "__main__":
for i in xrange(workers):
port = start_port + i
print 'process started on %d port' % port
p = Process(target=server_process, args=(port,))
p.start()
客户:
def f():
for i in xrange(500000):
try:
r = requests.get('http://127.0.0.1:4400')
if i % 100 == 0:
print i, str(r.text)
except:
print traceback.format_exc()
time.sleep(5)
if __name__ == '__main__':
for j in xrange(1):
p = Process(target=f)
p.start()
追溯:
Traceback (most recent call last):
File "/home/me/PycharmProjects/test/client.py", line 16, in f
if i % 100 == 0:
File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 55, in get
return request('get', url, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 44, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 383, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 486, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 378, in send
raise ConnectionError(e)
ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=4400): Max retries exceeded with url: / (Caused by <class 'socket.error'>: [Errno 99] Cannot assign requested address)
更新:
实验性地选择了硬件服务器(不是进程)每秒 300 个请求的值。此值不依赖于运行 tornado 的进程数。添加 nginx 作为代理服务器没有帮助。
服务器在 ubuntu server 12.04 和 linux mint 16 上运行。看起来这个限制取决于 debian 操作系统。
【问题讨论】:
-
tornado 是单线程的,可能由于服务器无法处理所有请求而备份请求:papercruncher.com/2013/01/15/truly-async-with-tornado
-
您的客户端仅向一个运行在端口 4400 上的进程发送请求。也许这就是您在更改服务器进程数时没有发现差异的原因。
-
出于好奇:如果每个请求只返回一个字符而不是 1000 个字符,每秒的请求数会增加到几万吗?
-
每个进程看到 300 个请求/秒的原因是因为 tornado 一次只能处理一个请求。要构建您返回的随机字符串,在我的 PC 上大约需要 0.003 秒。每秒 1/0.003 ~ 333 个请求。
-
在这个例子中端口是硬编码的。其他测试需要更多服务器脚本中的工作人员和客户端脚本中的随机端口。 A 在一个字符处获得了 400req/sec 的数据,但在大约 36000 个请求之后,服务器再次变得不可用。问题是服务器不可用,而不是 req/sec。