我们在RedHat OS上运行Tornado 3.0服务并收到以下错误:
[E 140102 17:07:37 ioloop:660] Exception in I/O handler for fd 11
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 653, in start
self._handlers[fd](fd, events)
File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 241, in wrapped
callback(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/tornado/netutil.py", line 136, in accept_handler
connection, address = sock.accept()
File "/usr/lib/python2.7/socket.py", line 202, in accept
error: [Errno 24] Too many open files
但我们无法弄清楚这意味着什么。
我们的龙卷风代码如下:
import sys
from tornado.ioloop import IOLoop
from tornado.options import parse_command_line, define, options
from tornado.httpserver import HTTPServer
from tornado.netutil import bind_sockets
import tornado
sys.path.append("..")
from tornado.web import RequestHandler, Application
from shared.bootstrap import *
from time import time
from clients import ClientFactory
from shared.configuration import Config
from shared.logger import Logger
from algorithms.neighborhood.application import NeighborhoodApplication
import traceback
define('port', default=8000, help="Run on the given port", type=int)
define('debug', default=True, help="Run application in debug mode", type=bool)
class WService(RequestHandler):
_clients = {}
def prepare(self):
self._start_time = time()
RequestHandler.prepare(self)
def get(self, algorithm = None):
self.add_header('Content-type', 'application/json')
response = {'skus' : []}
algorithm = 'neighborhood' if not algorithm else algorithm
try:
if not algorithm in self._clients:
self._clients[algorithm] = ClientFactory.get_instance(algorithm)
arguments = self.get_arguments_by_client(self._clients[algorithm].get_expected_arguments())
response['skus'] = app.get_manager().make_recommendations(arguments)
self.write(response)
except Exception as err:
self.write(response)
error("Erro: " + str(err))
def get_arguments_by_client(self, expected_arguments):
arguments = {}
for key in expected_arguments:
arguments[key] = self.get_argument(key, expected_arguments[key])
return arguments
def on_connection_close(self):
self.finish({'skus':[]})
RequestHandler.on_connection_close(self)
def on_finish(self):
response_time = 1000.0 *(time() - self._start_time)
log("%d %s %.2fms" % (self.get_status(), self._request_summary(), response_time))
RequestHandler.on_finish(self)
def handling_exception(signal, frame):
error('IOLoop blocked for %s seconds in\n%s\n\n' % ( io_loop._blocking_signal_threshold, ''.join(traceback.format_stack(frame)[-3:])))
if __name__ == "__main__":
configuration = Config()
Logger.configure(configuration.get_configs('logger'))
app = NeighborhoodApplication({
'application': configuration.get_configs('neighborhood'),
'couchbase': configuration.get_configs('couchbase'),
'stock': configuration.get_configs('stock')
})
app.run()
log("Neighborhood Matrices successfully created...")
log("Initiating Tornado Service...")
parse_command_line()
application = Application([
(r'/(favicon.ico)', tornado.web.StaticFileHandler, {"path": "./images/"}),
(r"/(.*)", WService)
], **{'debug':options.debug, 'x-headers' : True})
sockets = bind_sockets(options.port, backlog=1024)
server = HTTPServer(application)
server.add_sockets(sockets)
io_loop = IOLoop.instance()
io_loop.set_blocking_signal_threshold(.05, handling_exception)
io_loop.start()
这是一个非常基本的脚本,基本上它获取了URL,在make_recommendation
函数中处理它并发回响应。
我们尝试通过io_loop.set_blocking_signal_threshold
函数设置50毫秒的龙卷风超时,因为有时URL的处理可能需要很长时间。
系统每分钟接收大约8000个请求,它工作正常约30分钟,但之后开始抛出“太多文件错误”并崩溃。一般来说,请求大约需要20毫秒来处理,但是当错误开始发生时,消耗的时间会突然增加到几秒钟。
我们试图查看端口8000有多少连接,并且它有几个打开的连接都具有“ESTABLISHED”状态。
我们的龙卷风脚本有什么问题吗?我们认为我们的超时功能无法正常工作,但到目前为止我们所研究的一切似乎都没问题。
如果您需要更多信息,请告诉我。
提前致谢,
答案 0 :(得分:13)
许多Linux发行版的每个进程的打开文件数量非常低(例如250)。你可以使用" ulimit -n"查看系统上的当前值(确保在与tornado服务器运行相同的环境中发出此命令)。要提高限制,您可以使用ulimit命令或修改/etc/security/limits.conf
(尝试将其设置为50000)。
Tornado的HTTP服务器(从3.2版开始)没有关闭Web浏览器打开的连接,因此空闲连接可能会随着时间的推移而累积。这就是为什么建议在Tornado服务器前使用像nginx或haproxy这样的代理的原因之一;这些服务器对这个和其他潜在的DoS问题更加强硬。