Я написал базовый FTP-сервер с pyftpdlib, используя Django для управления пользователями. Я ошибочно предположил, что Django позаботится о соединении с БД и просто автоматически переподключится после истечения времени ожидания.
EDIT: Просто для уточнения: это не веб-служба Django, а демон, который работает на сервере только с использованием Django для простого интерфейса базы данных. Я делаю это, потому что веб-сайт, который помещает данные в базу данных, делает это с помощью django. Поэтому я подумал, что это может быть легко сделать и на стороне демона, вместо того, чтобы писать свои собственные запросы.
Теперь каждые несколько часов я получаю это:
OperationalError(2006, 'MySQL server has gone away')
В основном это происходит, когда никто не использует сервер в течение ночи, поэтому кажется, что есть тайм-аут БД, а затем кто-то входит в систему утром, что заставляет службу FTP запрашивать БД для пароля и имени пользователя, используя модель Django.
Как мне теперь убедиться, что соединение не пропало? Есть ли какая-либо комбинация try/except, чтобы легко проверить, живо ли соединение, а не просто переподключиться?
Вот как я это сделал. Короче говоря, я храню django.contrib.auth.User в self.auth моего FTP-класса, а затем, когда мне нужно проверить, я просто спрашиваю self.auth.models.Users для проверки. Опять же, я предположил, что если бы был тайм-аут, django позаботился бы об этом.
Есть ли что-нибудь, что я могу сделать, чтобы проверить django и переподключиться? Или как я могу изменить свой код, чтобы этого не произошло?
class DjangoMysqlConnector:
def __init__(self,SystemLogger=False, BASIC_CONFIG=False):
self.queue = Queue.Queue()
self.lock = threading.Lock()
sys.path.append("/home/user/git/apps")
if not BASIC_CONFIG:
sys.path.append("/home/user/django/bildverteiler_project")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "bildverteiler_project.settings")
else:
sys.path.append(BASIC_CONFIG["project_path"])
os.environ.setdefault("DJANGO_SETTINGS_MODULE", os.path.basename(BASIC_CONFIG["project_path"])+".settings")
django.setup()
import bildverteiler
from django.contrib import auth
self.auth = auth
class CustomDummyAuthorizer(DummyAuthorizer):
def __init__(self,user_query,*args,**kwargs):
super(CustomDummyAuthorizer,self).__init__()
self.user_query = user_query
def validate_authentication(self, username, password, arg):
try:
user_obj = self.user_query.objects.get(username=username)
except:
print "user does not exist: "+str(sys.exc_info())
raise AuthenticationFailed("failed")
else:
if not self.has_user(username):
try:
os.makedirs("/home/user/git/verteilerCore2/default_basedir/in/"+str(user_obj.pk))
except OSError:
pass
self.add_user(user_obj.username, 'xxx', "/home/user/git/verteilerCore2/default_basedir/in/"+str(user_obj.pk), perm='elradfmwM')
if user_obj.check_password(password):
print "password geht"
return None
else:
print "password wrong"
raise AuthenticationFailed("failed")
class FtpThread(threading.Thread):
def __init__(self, user_query):
self.user_query = user_query
self.killswitch = 0
threading.Thread.__init__(self)
self.setDaemon(True)
def run(self,*args,**kwargs):
authorizer = CustomDummyAuthorizer(self.user_query)
handler = FTPHandler
handler.authorizer = authorizer
logging.basicConfig(filename='/var/log/verteiler_ftp.log', level=logging.WARN)
handler.banner = "pyftpdlib based ftpd ready."
address = ('', 21)
self.server = FTPServer(address, handler)
self.server.max_cons = 256
self.server.max_cons_per_ip = 30
self.server.serve_forever()
def stop(self):
self.server.close_all()