我正在尝试使用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)
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
和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的分叉有关。但除此之外,我还不清楚需要做什么。
答案 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 时,我的应用程序开始出现此问题。当我删除该选项时,我的应用程序恢复正常运行。