uWSGI,Flask,sqlalchemy和postgres:SSL错误:解密失败或错误记录mac

时间:2014-03-31 02:01:11

标签: postgresql nginx sqlalchemy flask uwsgi

我正在尝试使用uWSGI + Nginx设置应用程序网络服务器,它使用SQLAlchemy运行Flask应用程序与Postgres数据库通信。

当我向网络服务器发出请求时,其他所有响应都将是500错误。

错误是:

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

错误由简单的Flask-SQLAlchemy方法触发:

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

uwsgisupervisor管理,其中包含配置:

[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

uwsgi的配置如下:

[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

我能得到的最远的是它与uwsgi的分叉有关。但除此之外,我还不清楚需要做什么。

4 个答案:

答案 0 :(得分:72)

这个问题最终成了uwsgi的分叉。

使用主进程处理多个进程时,uwsgi在主进程中初始化应用程序,然后将应用程序复制到每个工作进程。问题是如果在初始化应用程序时打开数据库连接,则会有多个进程共享同一连接,从而导致上述错误。

解决方案是设置lazy configuration option for uwsgi,这会强制在每个流程中完全加载应用程序:

  

lazy

     

设置延迟模式(在工作人员而非主人中加载应用程序)。

     

此选项可能会影响内存使用,因为无法使用Copy-on-Write语义。启用延迟时,只有工作人员将通过uWSGI的重载信号重新加载;主人将活着。因此,主服务器在重新加载时不会获取uWSGI配置更改。

还有一个lazy-apps选项:

  

lazy-apps

     

在每个工作人员而不是主人中加载应用程序。

     

此选项可能会影响内存使用,因为无法使用Copy-on-Write语义。与惰性不同,这只会影响应用程序的加载方式,而不会影响主服务器在重新加载时的行为。

这个uwsgi配置最终为我工作:

[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

答案 1 :(得分:1)

作为替代方案,您可以配置引擎。这就是我解决问题的方法。

如果在创建应用期间存在查询,也就是在创建应用本身的模块中,则可能会发生此类问题。如果说明了,引擎会分配一个连接池,然后分配uwsgi分叉。

通过调用' engine.dispose()',连接池本身将关闭,一旦有人再次开始查询,就会出现新的连接。因此,如果您在创建应用程序的模块末尾执行此操作,则会在UWSGI fork之后创建新连接。

答案 2 :(得分:0)

如果您使用Flask,可以查看我的回复 https://stackoverflow.com/a/59527801/4851716

//

我在Heroku中遇到了烧瓶+ Peewee + rq的错误。

如果您有一个与RQ一起使用的简单应用程序,建议您使用SimpleWorker

RQ建议使用rq.worker.HerokuWorker,但是我仍然遇到ssl错误。 该错误出现在我创建一个后续(链)任务的情况下,执行1取决于另一个任务的成功。

我也在使用flask-rq2,但也适用于常规用法

# app.py
app = Flask(__name__)
app.config['RQ_WORKER_CLASS'] = os.getenv('RQ_WORKER_CLASS', 'rq.worker.Worker')
rq = RQ(app)

在heroku配置中     将您的RQ_WORKER_CLASS设置为rq.worker.SimpleWorker

答案 3 :(得分:0)

我正在 Heroku 上使用 gunicorn 运行一个烧瓶应用程序。当我将 --preload 选项添加到我的 Procfile 时,我的应用程序开始出现此问题。当我删除该选项时,我的应用程序恢复正常运行。