J'ai une application Web Flask qui fonctionnait sur un serveur autonome en utilisant les éléments suivants:
Sur le serveur autonome, cette application fonctionnait correctement.
J'ai depuis "dockerized" cette application sur deux conteneurs:
Depuis la dockerisation, j'obtiens parfois cette erreur (tout le suivi posté à la fin):
Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context context) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute cursor.execute(statement, parameters) File "/usr/local/lib/python3.6/site-packages/pymysql/cursors.py", line 170, in execute result = self._query(query) File "/usr/local/lib/python3.6/site-packages/pymysql/cursors.py", line 328, in _query conn.query(q) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 517, in query self._affected_rows = self._read_query_result(unbuffered=unbuffered) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 732, in _read_query_result result.read() File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 1075, in read first_packet = self.connection._read_packet() File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 657, in _read_packet packet_header = self._read_bytes(4) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 707, in _read_bytes CR.CR_SERVER_LOST, "Lost connection to MySQL server during query") pymysql.err.OperationalError: (2013, 'Lost connection to MySQL server during query') The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 2292, in wsgi_app response = self.full_dispatch_request() File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1815, in full_dispatch_request rv = self.handle_user_exception(e) File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1718, in handle_user_exception reraise(exc_type, exc_value, tb) File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 35, in reraise raise value File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request rv = self.dispatch_request() File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request return self.view_functions[rule.endpoint](**req.view_args) File "/usr/local/lib/python3.6/site-packages/flask_user/decorators.py", line 132, in decorator allowed = _is_logged_in_with_confirmed_email(user_manager) File "/usr/local/lib/python3.6/site-packages/flask_user/decorators.py", line 17, in _is_logged_in_with_confirmed_email if user_manager.call_or_get(current_user.is_authenticated): File "/usr/local/lib/python3.6/site-packages/werkzeug/local.py", line 347, in __getattr__ return getattr(self._get_current_object(), name) File "/usr/local/lib/python3.6/site-packages/werkzeug/local.py", line 306, in _get_current_object return self.__local() File "/usr/local/lib/python3.6/site-packages/flask_login/utils.py", line 26, in <lambda> current_user = LocalProxy(lambda: _get_user()) File "/usr/local/lib/python3.6/site-packages/flask_login/utils.py", line 335, in _get_user current_app.login_manager._load_user() File "/usr/local/lib/python3.6/site-packages/flask_login/login_manager.py", line 359, in _load_user return self.reload_user() File "/usr/local/lib/python3.6/site-packages/flask_login/login_manager.py", line 321, in reload_user user = self.user_callback(user_id) File "/usr/local/lib/python3.6/site-packages/flask_user/user_manager.py", line 130, in load_user_by_user_token user = self.db_manager.UserClass.get_user_by_token(user_token) File "/usr/local/lib/python3.6/site-packages/flask_user/user_mixin.py", line 51, in get_user_by_token user = user_manager.db_manager.get_user_by_id(user_id) File "/usr/local/lib/python3.6/site-packages/flask_user/db_manager.py", line 179, in get_user_by_id return self.db_adapter.get_object(self.UserClass, id=id) File "/usr/local/lib/python3.6/site-packages/flask_user/db_adapters/sql_db_adapter.py", line 48, in get_object return ObjectClass.query.get(id) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 924, in get ident, loading.load_on_pk_identity) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 1007, in _get_impl return db_load_fn(self, primary_key_identity) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/loading.py", line 250, in load_on_pk_identity return q.one() File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2954, in one ret = self.one_or_none() File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2924, in one_or_none ret = list(self) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2995, in __iter__ return self._execute_and_instances(context) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3018, in _execute_and_instances result = conn.execute(querycontext.statement, self._params) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 948, in execute return meth(self, multiparams, params) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 269, in _execute_on_connection return connection._execute_clauseelement(self, multiparams, params) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1060, in _execute_clauseelement compiled_sql, distilled_params File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1200, in _execute_context context) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1413, in _handle_dbapi_exception exc_info File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 265, in raise_from_cause reraise(type(exception), exception, tb=exc_tb, cause=cause) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 248, in reraise raise value.with_traceback(tb) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1193, in _execute_context context) File "/usr/local/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 509, in do_execute cursor.execute(statement, parameters) File "/usr/local/lib/python3.6/site-packages/pymysql/cursors.py", line 170, in execute result = self._query(query) File "/usr/local/lib/python3.6/site-packages/pymysql/cursors.py", line 328, in _query conn.query(q) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 517, in query self._affected_rows = self._read_query_result(unbuffered=unbuffered) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 732, in _read_query_result result.read() File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 1075, in read first_packet = self.connection._read_packet() File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 657, in _read_packet packet_header = self._read_bytes(4) File "/usr/local/lib/python3.6/site-packages/pymysql/connections.py", line 707, in _read_bytes CR.CR_SERVER_LOST, "Lost connection to MySQL server during query") sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2013, 'Lost connection to MySQL server during query') [SQL: 'SELECT user.is_active AS user_is_active, user.id AS user_id, user.username AS user_username, user.password AS user_password, user.reset_password_token AS user_reset_password_token, user.email AS user_email, user.email_confirmed_at AS user_email_confirmed_at, user.first_name AS user_first_name, user.last_name AS user_last_name \nFROM user \nWHERE user.id = %(param_1)s'] [parameters: {'param_1': 13}] (Background on this error at: http://sqlalche.me/e/e3q8)
Le journal MariaDB affiche les erreurs suivantes avec une journalisation détaillée:
version: "3.7" services: db: restart: "always" build: ./docker/db volumes: - "~/db:/var/lib/mysql" environment: MYSQL_ROOT_PASSWORD: "password" MYSQL_DATABASE: "database" MYSQL_USER: "user" MYSQL_PASSWORD: "password" ports: - '3306:3306' nginx-uwsgi-flask: restart: "always" depends_on: - "db" build: context: . dockerfile: ./docker/nginx-uwsgi-flask/Dockerfile volumes: - "~/data/fileshare:/fileshare" ports: - "80:80" - "443:443" network_mode: "host"
Ceci est vécu par l'utilisateur comme une 502 Bad Gateway
. Si l'utilisateur actualise la page, cela résoudra souvent le problème. Ce problème survient au hasard. Je n'ai pas pu le reproduire à volonté, mais avec le temps il apparaîtra inévitablement.
Qu'est-ce qui cause ce problème et comment puis-je le résoudre?
Ce que j'ai fait:
pool_recycle
sur 120
scoped_session
qui devrait éviter ces problèmes de temporisation.network_mode
par défaut par un commentaire. Cela n'a pas résolu le problème.Je pense que cela agit comme si la connexion entre flask et la base de données n'était pas fiable, mais en tant que conteneurs docker fonctionnant sur le même hôte, cela ne devrait-il pas être assez fiable?
Code pertinent:
database.py
class Config: ... SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://username:password@127.0.0.1/database?charset=utf8mb4' SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ENGINE_OPTIONS = { 'pool_recycle': 120 } ...
config.py
from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy()
docker-compose.yml
2020-05-10 18:35:32 130 [Warning] Aborted connection 130 to db: 'flspection2' user: 'fl-server' host: '172.19.0.1' (Got an error reading communication packets) 2020-05-10 18:45:34 128 [Warning] Aborted connection 128 to db: 'flspection2' user: 'fl-server' host: '172.19.0.1' (Got timeout reading communication packets)
retraçage
Lost connection to MySQL server during query
4 Réponses :
Je ne sais pas quelles versions vous utilisez mais avez-vous essayé de définir 'SQLALCHEMY_POOL_SIZE et' SQLALCHEMY_POOL_RECYCLE '
J'ai été confronté à un problème similaire car j'ai une application django multithread. Lorsque le thread essaie d'accéder à la base de données, la connexion a été perdue. Il y a un bug django. https://code.djangoproject.com/ticket/21597
vous pouvez le résoudre avec cette solution de contournement.
from django.db import connection def is_connection_usable(): try: connection.connection.ping() except: return False else: return True def do_work(): while(True): # Endless loop that keeps the worker going (simplified) if not is_connection_usable(): connection.close() try: do_a_bit_of_work() except: logger.exception("Something bad happened, trying again") ââââââââââââââââ çæå£°æï¼æ¬æä¸ºCSDNå主ãorangleliuãçååæç« ï¼éµå¾ªCC 4.0 BY-SAçæåè®®ï¼è½¬è½½è¯·éä¸åæåºå¤é¾æ¥åæ¬å£°æã åæé¾æ¥ï¼https://blog.csdn.net/lzz957748332/java/article/details/41480417
Vérifiez d'abord votre connexion à la base de données, si la connexion est perdue, elle fermera votre connexion, lorsque vous tenterez à nouveau de vous connecter, vous vous connecterez.
Bkz https://blog.csdn.net/lzz957748332/article/details/41480417
Essayez ce qui suit pour exclure que vous ayez des connexions obsolètes dans votre pool:
Depuis https://docs.sqlalchemy.org/en/13/core/ Covoiturage.html#pool-disconnects
L'approche ajoute un peu de surcharge au processus de vérification de la connexion, mais elle est par ailleurs l'approche la plus simple et la plus fiable pour éliminer complètement les erreurs de base de données dues à des connexions mises en pool obsolètes. L'application appelante n'a pas besoin de se préoccuper de l'organisation des opérations pour pouvoir récupérer des connexions périmées extraites du pool.
Le test pessimiste des connexions lors de la vérification est réalisable en utilisant l'argument Pool.pre_ping, disponible depuis create_engine () via l'argument create_engine.pool_pre_ping:
engine = create_engine("mysql+pymysql://user:pw@host/db", pool_pre_ping=True)
Cela n'a pas résolu le problème pour moi
J'ai résolu ce problème en migrant d'un conteneur mariadb
vers mysql
. Je ne sais toujours pas quelle est la cause profonde.
Après avoir essayé toutes les solutions recommandées et perdu beaucoup d'argent à cause de ce bogue ridicule, je pense que c'est l'option la plus judicieuse.
Voyez-vous quelque chose dans les journaux MariaDB? Pouvez-vous essayer d'augmenter le niveau de journalisation du serveur?
@MikkoOhtamaa - J'ai édité la question avec ce qui apparaît dans le journal MariaDB lorsque cela se produit. Je vais chercher à augmenter le niveau de journalisation. Je ne sais pas comment faire ça du haut de ma tête.
log_warnings=9
niveau de journalisation (log_warnings=9
). Mettra à jour lorsque je capture à nouveau l'erreur.Aussi - ce n'était pas lié à MariaDB, mais c'est arrivé avec moi il y a longtemps. Le pilote PostgreSQL Python (écrit en C) plantait. Le passage à un pilote Pure Python a aidé. C'était difficile à diagnostiquer car il ne laissait aucune trace dans les journaux.
Changer le niveau de journalisation n'a pas donné beaucoup d'informations supplémentaires, mais j'ai vu qu'il y avait deux erreurs légèrement différentes en cours (éditées ci-dessus). 1. "Vous avez une erreur lors de la lecture des paquets de communication" et 2. "Vous avez dépassé le délai de lecture des paquets de communication"
@MikkoOhtamaa - Pymysql est le pilote python pur. Je teste actuellement mysqldb qui est la bibliothèque C. Peut-être qu'avec Maria DB, le problème sera résolu dans l'autre sens.
Selon la version, Flask-SQLalchemy a quelques autres paramètres par défaut qui pourraient affecter cela. Avez-vous essayé de définir SQLALCHEMY_POOL_SIZE, SQLALCHEMY_POOL_TIMEOUT et SQLALCHEMY_MAX_OVERFLOW?
Pourquoi utilisez-vous
network_mode
commehost
et utilisezSQLALCHEMY_DATABASE_URI = 'mysql+pymysql://username:password@db/database?charset=utf8mb4'
@TarunLalwani - Je l'ai fait de cette façon parce qu'après avoir joué, c'est ce qui semblait fonctionner. Je déduis de votre question qu'il existe un meilleur moyen?
@MattL. - J'ai seulement essayé le SQLALCHEMY_POOL_TIMEOUT. Ce n'est pas une utilisation intensive et j'ai rencontré ce problème après des heures où je suis certain que personne d'autre ne l'utilise, donc je ne m'attends pas à ce que pool_size ou max_overflow entrent en jeu.
Bien reçu! Il vaut toujours la peine de vérifier.
@TarunLalwani - Je pense que j'ai initialement mal interprété votre commentaire. J'ai changé le
network_mode
à la valeur par défaut et mis à jour leSQLALCHEMY_DATABASE_URI
comme suggéré. Je mettrai à jour quand j'aurai des informations de déménagement.Le changement de
network_mode
n'a pas résolu le problème.Cela semble être un problème de réseau de docker entre les conteneurs. Jetez un coup d'oeil s'il vous plait. success.docker.com/article/troubleshooting-container-network ing