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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22752521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 01:23:03  来源:igfitidea点击:

uWSGI, Flask, sqlalchemy, and postgres: SSL error: decryption failed or bad record mac

postgresqlnginxsqlalchemyflaskuwsgi

提问by frnsys

I'm trying to setup an application webserver using uWSGI + Nginx, which runs a Flask application using SQLAlchemy to communicate to a Postgres database.

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

When I make requests to the webserver, every other response will be a 500 error.

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

The error is:

错误是:

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

The error is triggered by a simple Flask-SQLAlchemymethod:

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

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


uwsgiis being managed by supervisor, which has a config:

uwsgi由 管理supervisor,它有一个配置:

[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

and uwsgi's config looks like:

anduwsgi的配置如下:

[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 furthest that I can get is that it has something to do with uwsgi's forking. But beyond that I'm not clear on what needs to be done.

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

回答by frnsys

The issue ended up being uwsgi's forking.

问题最终是 uwsgi 的分叉。

When working with multiple processes with a master process, uwsgi initializes the application in the master process and then copies the application over to each worker process. The problem is if you open a database connection when initializing your application, you then have multiple processes sharing the same connection, which causes the error above.

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

The solution is to set the lazyconfiguration option for uwsgi, which forces a complete loading of the application in each process:

解决方案是lazy为 uwsgi设置配置选项,这会强制在每个进程中完整加载应用程序:

lazy

Set lazy mode (load apps in workers instead of master).

This option may have memory usage implications as Copy-on-Write semantics can not be used. When lazy is enabled, only workers will be reloaded by uWSGI's reload signals; the master will remain alive. As such, uWSGI configuration changes are not picked up on reload by the master.

lazy

设置懒惰模式(在工作人员而不是主人中加载应用程序)。

由于无法使用 Copy-on-Write 语义,此选项可能会影响内存使用情况。当启用lazy 时,只有worker 会被uWSGI 的重新加载信号重新加载;主人会活着。因此,主服务器不会在重新加载时获取 uWSGI 配置更改。

There's also a lazy-appsoption:

还有一个lazy-apps选项:

lazy-apps

Load apps in each worker instead of the master.

This option may have memory usage implications as Copy-on-Write semantics can not be used. Unlike lazy, this only affects the way applications are loaded, not master's behavior on reload.

lazy-apps

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

由于无法使用 Copy-on-Write 语义,此选项可能会影响内存使用情况。与lazy 不同,这只影响应用程序的加载方式,而不影响master 在重新加载时的行为。

This uwsgi configuration ended up working for me:

这个 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

回答by fcracker79

As an alternative you might dispose the engine. This is how I solved the problem.

作为替代方案,您可以处置发动机。这就是我解决问题的方法。

Such issues may happen if there is a query during the creation of the app, that is, in the module that creates the app itself. If that states, the engine allocates a pool of connections and then uwsgi forks.

如果在创建应用程序的过程中,即在创建应用程序本身的模块中存在查询,则可能会出现此类问题。如果出现这种情况,引擎会分配一个连接池,然后 uwsgi 分叉。

By invoking 'engine.dispose()', the connection pool itself is closed and new connections will come up as soon as someone starts making queries again. So if you do that at the end of the module where you create your app, new connections will be created after the UWSGI fork.

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