web-dev-qa-db-fra.com

uWSGI, Flask, sqlalchemy et postgres: erreur SSL: échec du déchiffrement ou mauvais enregistrement mac

J'essaie de configurer un serveur Web d'application en utilisant uWSGI + Nginx, qui exécute une application Flask utilisant SQLAlchemy pour communiquer avec une base de données Postgres.

Lorsque je fais des demandes au serveur Web, chaque autre réponse sera une erreur 500.

L'erreur est:

Traceback (most recent call last):
  File "/var/env/argos/lib/python3.3/site-packages/sqlalchemy/engine/base.py", line 867, in _execute_context
    context)
  File "/var/env/argos/lib/python3.3/site-packages/sqlalchemy/engine/default.py", line 388, in do_execute
    cursor.execute(statement, parameters)
psycopg2.OperationalError: SSL error: decryption failed or bad record mac


The above exception was the direct cause of the following exception:

sqlalchemy.exc.OperationalError: (OperationalError) SSL error: decryption failed or bad record mac

L'erreur est déclenchée par un simple Flask-SQLAlchemy méthode:

result = models.Event.query.get(id)

uwsgi est géré par supervisor, qui a une configuration:

[program:my_app]
command=/usr/bin/uwsgi --ini /etc/uwsgi/apps-enabled/myapp.ini --catch-exceptions
directory=/path/to/my/app
stopsignal=QUIT
autostart=true
autorestart=true

et la configuration de uwsgi ressemble à:

[uwsgi]
socket = /tmp/my_app.sock
logto = /var/log/my_app.log
plugins = python3
virtualenv =  /path/to/my/venv
pythonpath = /path/to/my/app
wsgi-file = /path/to/my/app/application.py
callable = app
max-requests = 1000
chmod-socket = 666
chown-socket = www-data:www-data
master = true
processes = 2
no-orphans = true
log-date = true
uid = www-data
gid = www-data

Le plus loin que je puisse obtenir, c'est que cela a quelque chose à voir avec la fourche d'Uwsgi. Mais au-delà de cela, je ne suis pas clair sur ce qui doit être fait.

36
frnsys

Le problème a fini par être la fourche d'Uwsgi.

Lorsque vous travaillez avec plusieurs processus avec un processus maître, uwsgi initialise l'application dans le processus maître, puis copie l'application sur chaque processus de travail. Le problème est que si vous ouvrez une connexion à une base de données lors de l'initialisation de votre application, plusieurs processus partagent la même connexion, ce qui provoque l'erreur ci-dessus.

La solution consiste à définir lazyoption de configuration pour uwsgi , ce qui force un chargement complet de l'application dans chaque processus:

lazy

Définissez le mode paresseux (chargez les applications dans les travailleurs au lieu du maître).

Cette option peut avoir des implications sur l'utilisation de la mémoire car la sémantique de copie sur écriture ne peut pas être utilisée. Lorsque lazy est activé, seuls les travailleurs seront rechargés par les signaux de rechargement de uWSGI; le maître restera vivant. En tant que tel, les modifications de configuration uWSGI ne sont pas récupérées lors du rechargement par le maître.

Il y a aussi un lazy-apps option:

lazy-apps

Chargez des applications dans chaque travailleur au lieu du maître.

Cette option peut avoir des implications sur l'utilisation de la mémoire car la sémantique de copie sur écriture ne peut pas être utilisée. Contrairement à lazy, cela n'affecte que la façon dont les applications sont chargées, pas le comportement du maître lors du rechargement.

Cette configuration uwsgi a fini par fonctionner pour moi:

[uwsgi]
socket = /tmp/my_app.sock
logto = /var/log/my_app.log
plugins = python3
virtualenv =  /path/to/my/venv
pythonpath = /path/to/my/app
wsgi-file = /path/to/my/app/application.py
callable = app
max-requests = 1000
chmod-socket = 666
chown-socket = www-data:www-data
master = true
processes = 2
no-orphans = true
log-date = true
uid = www-data
gid = www-data

# the fix
lazy = true
lazy-apps = true
80
frnsys

Vous pouvez également disposer du moteur. C'est ainsi que j'ai résolu le problème.

De tels problèmes peuvent se produire s'il y a une requête lors de la création de l'application, c'est-à-dire dans le module qui crée l'application elle-même. Si cela indique, le moteur alloue un pool de connexions, puis les fourches uwsgi.

En appelant 'engine.dispose ()', le pool de connexions lui-même est fermé et de nouvelles connexions apparaîtront dès que quelqu'un recommencera à effectuer des requêtes. Donc, si vous le faites à la fin du module où vous créez votre application, de nouvelles connexions seront créées après le fork UWSGI.

1
fcracker79