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 120scoped_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=9niveau 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_modecommehostet 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_URIcomme suggéré. Je mettrai à jour quand j'aurai des informations de déménagement.Le changement de
network_moden'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