gevent.monkey.patch_all()后的max_user_connections问题
我正在使用gevent-socketio v0.13.8来开发一个基于Django的聊天应用。我的数据库是MySql,最大用户连接数设置为1500。我的socket服务器是用Python的守护进程运行的。最开始我没有使用猴子补丁(monkey patching),服务器运行得很好,除了当某个绿色线程(greenlet)出错时,整个系统就会崩溃,出现SystemExit错误,之后就再也无法建立连接了。解决办法就是重启整个服务器。
不过我不想每次都重启服务器。最后我想到了猴子补丁这个方法。我不确定这是否能解决我的问题,但我希望我的socket服务器即使在绿色线程出现未处理异常导致SystemExit时也能继续运行。
于是我在服务器启动的函数中使用了gevent.monkey.patch_all()。现在我遇到的主要问题是:在连接了3到4次后,MySql出现了以下错误:
User xxx already has more than 'max_user_connections' active connections
我的MySql服务器的max_user_connection变量设置为1500。我觉得可能是某些东西在绿色线程中创建了新的数据库连接。
顺便提一下,当我使用:
monkey.patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=True, aggressive=True)
而不是:
monkey.patch_all()
时,max_user_connection错误就不会出现。有没有办法在不出现这个错误的情况下使用猴子补丁?如果我在问题描述中遗漏了什么信息,请告诉我,我会立即更新。
这是我的守护进程服务器代码:
class App():
def __init__(self):
self.stdin_path = 'xxx.txt'
self.stdout_path = 'xxx.txt'
self.stderr_path = 'xxx.txt'
self.pidfile_path = 'xxx.pid'
self.pidfile_timeout = 5
def run(self):
from socketio.server import SocketIOServer
from gevent import monkey
monkey.patch_all()
while True:
try:
bind = ("xx.xx.xx.xx", xxxx)
handler = get_handler()
server = SocketIOServer(bind, handler, resource="socket.io",policy_server=False)
server.serve_forever()
except:
server.kill()
app = App()
logger = logging.getLogger("DaemonLog")
logger.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler = logging.FileHandler("xxx.log")
handler.setFormatter(formatter)
logger.addHandler(handler)
daemon_runner = runner.DaemonRunner(app)
daemon_runner.daemon_context.files_preserve=[handler.stream]
daemon_runner.do_action()
1 个回答
1
我在这里找到了解决我问题的方法:https://github.com/abourget/gevent-socketio/issues/174
其实这个问题和没有关闭的数据库连接有关,这些连接是由绿色线程(greenlets)管理的。在我的命名空间类中添加了一个类似的异常处理装饰器之后,我就没有再看到“最大用户连接数”错误了。
from django.db import close_old_connections # Django 1.6
class MyNamespace(BaseNamespace):
...
def exception_handler_decorator(self, fun):
def wrap(*args, **kwargs):
try:
return fun(*args, **kwargs)
finally:
close_old_connections()
return wrap
...