如果我的 tornado 服务器上有很多连接,我会在日志中看到错误
Exception in callback (<socket._socketobject object at 0x7f0b9053e3d0>, <function null_wrapper at 0x7f0b9054c140>)
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/tornado/ioloop.py", line 888, in start
handler_func(fd_obj, events)
File "/usr/local/lib/python2.7/dist-packages/tornado/stack_context.py", line 277, in null_wrapper
return fn(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/tornado/netutil.py", line 276, in accept_handler
callback(connection, address)
File "/usr/local/lib/python2.7/dist-packages/tornado/tcpserver.py", line 264, in _handle_connection
File "/usr/local/lib/python2.7/dist-packages/tornado/netutil.py", line 517, in ssl_wrap_socket
context = ssl_options_to_context(ssl_options)
File "/usr/local/lib/python2.7/dist-packages/tornado/netutil.py", line 494, in ssl_options_to_context
context.load_cert_chain(ssl_options['certfile'], ssl_options.get('keyfile', None))
IOError: [Errno 24] Too many open files
并断开我的客户端。 Tornado 在 ewery 连接上打开 ssl 证书文件?
Tornado 应用
class VastWebSocket(tornado.websocket.WebSocketHandler):
connections = set()
current_connect = 0
current_user = 0
status_play_vast = False
def open(self):
c = Connection()
c.connection = self
VastWebSocket.connections.add(c)
self.current_connect = c
def on_message(self, msg):
data = json.loads(msg)
app_log.info("on message = " + msg)
if not 'status' in data:
return
if data["status"] == "start_vast":
VastWebSocket.status_play_vast = True
if data["status"] == "end_vast":
VastWebSocket.status_play_vast = False
app_log.info("status_play_vast = " + str(VastWebSocket.status_play_vast))
if data["status"] == "get_status_vast":
self.current_connect.connection.write_message({"status": VastWebSocket.status_play_vast})
return
for conn in self.connections:
conn.connection.write_message(msg)
def on_close(self):
if self.current_connect <> 0:
VastWebSocket.connections.remove(self.current_connect)
def check_origin(self, origin):
return True
从django命令启动tornado服务器
class Command(BaseCommand):
help = 'Starts the Tornado application for message handling.'
def add_arguments(self, parser):
parser.add_argument('port_number', nargs='+', type=int)
def sig_handler(self, sig, frame):
"""Catch signal and init callback"""
tornado.ioloop.IOLoop.instance().add_callback(self.shutdown)
def shutdown(self):
"""Stop server and add callback to stop i/o loop"""
self.http_server.stop()
io_loop = tornado.ioloop.IOLoop.instance()
io_loop.add_timeout(time.time() + 2, io_loop.stop)
def handle(self, *args, **options):
if "port_number" in options:
try:
port = int(options["port_number"][0])
except ValueError:
raise CommandError('Invalid port number specified')
else:
port = 8030
ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(os.path.join("/www/cert/", "rumma.crt"),
os.path.join("/www/cert/", "rumma.key"))
self.http_server = tornado.httpserver.HTTPServer(application, ssl_options = ssl_ctx)
self.http_server.bind(port, address="0.0.0.0")
self.http_server.start(1)
# Init signals handler
signal.signal(signal.SIGTERM, self.sig_handler)
# This will also catch KeyboardInterrupt exception
signal.signal(signal.SIGINT, self.sig_handler)
tornado.ioloop.IOLoop.instance().start()
为什么他打开很多文件,在我看来需要在启动服务器和所有文件中打开 ssl。 Stackoverflow 会询问更多信息,但最重要的是,所有信息都需要。
最佳答案
您的代码似乎运行多个进程或线程,它们都直接访问 ssl key 文件。 Linux 默认的 ulimit
很快就会变低,然后就会出现这个错误。
您可以通过以下方式检查当前设置:
$ ulimit -a
快速而肮脏的解决方案是增加这个值:
$ ulimit -n <new_value>
-n
选项甚至可以接受 unlimited
。
注意:您可以永久设置应用程序用户 .bashrc
文件的值。
在这两种情况下,您都需要注销然后登录才能使更改生效。
但是修改这个值有点脏,因为它是给定用户环境的全局值。
更难但更简洁的解决方案是找到一种方法,在您的应用程序加载时将文件内容加载到内存中,并使加载的值/变量可供所有进程访问。
关于Python tornado 打开的文件太多 Ssl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45968587/