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

frn*_*sys 36 postgresql sqlalchemy nginx flask uwsgi

我正在尝试使用uWSGI + Nginx设置应用程序webserver,它使用SQLAlchemy运行Flask应用程序与Postgres数据库进行通信.

当我向Web服务器发出请求时,每个其他响应都将是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
Run Code Online (Sandbox Code Playgroud)

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

result = models.Event.query.get(id)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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

frn*_*sys 78

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

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

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

lazy

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

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

还有一个lazy-apps选择:

lazy-apps

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

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

这个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
Run Code Online (Sandbox Code Playgroud)

  • 我想知道你是怎么想出来的?调试过程是什么样的? (9认同)
  • "请注意,有一个名为`lazy`的旧选项更具侵入性和高度劝阻(它仍然仅用于向后兼容)"来源:http://uwsgi-docs.readthedocs.org/en/latest/ThingsToKnow html的 (8认同)
  • 谢谢你回答自己.它今天帮助了我. (6认同)

fcr*_*r79 7

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

如果在创建应用程序期间(即创建应用程序本身的模块中)存在查询,则可能会出现此类问题。如果是这样,引擎会分配一个连接池,然后进行 uwsgi 分叉。

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

  • 这对我来说是一个更好的解决方案,因为我在分叉之前使用“gunicorn --preload”加载应用程序代码以降低内存使用量,所以我特别不想使用延迟加载。这实际上是 SQLAlchemy 文档中“engine.dispose()”的推荐用例:https://docs.sqlalchemy.org/en/13/core/connections.html#engine-disposal (3认同)