uWSGI, Flask, sqlalchemy e postgres: errore SSL: decifrazione fallita o cattivo record mac

Sto provando a configurare un server web dell’applicazione utilizzando uWSGI + Nginx, che esegue un’applicazione Flask che utilizza SQLAlchemy per comunicare con un database Postgres.

Quando faccio richieste al webserver, ogni altra risposta sarà un errore 500.

L’errore è:

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’errore è triggersto da un semplice metodo Flask-SQLAlchemy :

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

uwsgi è gestito dal supervisor , che ha una configurazione:

     [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 

    e la configurazione di uwsgi è simile a:

     [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 

    Il più lontano che posso ottenere è che ha qualcosa a che fare con la biforcazione di uwsgi. Ma oltre a ciò non sono chiaro su cosa debba essere fatto.

    Il problema ha finito per essere la biforcazione di uwsgi.

    Quando si lavora con più processi con un processo master, uwsgi inizializza l’applicazione nel processo master e quindi copia l’applicazione su ciascun processo di lavoro. Il problema è che se apri una connessione al database durante l’inizializzazione della tua applicazione, allora hai più processi che condividono la stessa connessione, il che causa l’errore sopra.

    La soluzione è impostare l’ opzione di configurazione lazy per uwsgi , che impone un caricamento completo dell’applicazione in ogni processo:

    lazy

    Imposta la modalità lazy (carica app in worker anziché master).

    Questa opzione potrebbe avere implicazioni sull’uso della memoria poiché non è ansible utilizzare la semantica Copy-on-Write. Quando è abilitato il pigro, solo i lavoratori saranno ricaricati dai segnali di ricarica di uWSGI; il maestro rimarrà vivo. Pertanto, le modifiche alla configurazione di uWSGI non vengono rilevate dal master.

    C’è anche un’opzione lazy-apps :

    lazy-apps

    Carica app in ogni worker anziché nel master.

    Questa opzione potrebbe avere implicazioni sull’uso della memoria poiché non è ansible utilizzare la semantica Copy-on-Write. A differenza di pigro, questo influenza solo il modo in cui le applicazioni vengono caricate, non il comportamento del master in fase di ricarica.

    Questa configurazione uwsgi ha finito per funzionare per me:

     [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 

    In alternativa si potrebbe smaltire il motore. Ecco come ho risolto il problema.

    Tali problemi possono verificarsi se esiste una query durante la creazione dell’app, ovvero nel modulo che crea l’app stessa. Se lo afferma, il motore assegna un pool di connessioni e quindi le forchette uwsgi.

    Richiamando ‘engine.dispose ()’, il pool di connessioni stesso viene chiuso e le nuove connessioni verranno visualizzate non appena qualcuno inizia a ripetere le query. Quindi, se lo fai alla fine del modulo in cui crei la tua app, verranno create nuove connessioni dopo il fork di UWSGI.