修复psycopg2.DatabaseError: error with status PGRES_TUPLES_OK and no message from the libpq
背景目前的项目使用Flask作为框架,Greenplum作为数据库搭了简单的后端,数据库连接选用的包是psycopg2。服务是使用uwsgi设置多进程多线程进行管理的,部署在k8s的环境中。前几天检查pod的log的时候发现后端的服务会对部分client发来的post请求返回 500 Internal Error,导致再做相应条目的get查询会出现以下错误:psycopg2.DatabaseErr
背景
目前的项目使用Flask作为框架,Greenplum作为数据库搭了简单的后端,数据库连接选用的包是psycopg2。服务是使用uwsgi设置多进程多线程进行管理的,部署在k8s的环境中。
前几天检查pod的log的时候发现后端的服务会对部分client发来的post请求返回 500 Internal Error
,导致再做相应条目的get查询会出现以下错误:
psycopg2.DatabaseError: error with status PGRES_TUPLES_OK and no message from the libpq
原因
因为测试时用的脚本有短时间内一定数量的并发请求,猜测是和多进程下的数据库连接失败有关。看了下psycopg在Github上的issue,恰好有相似的问题,证实了之前的猜想,也给出了非常好的解决方案。参考链接:(DatabaseError) error with no message from the libpq
可以直接拉到issue的最后,给出了这种错误的原因。
@https://github.com/dibrovsd
Found. This happens when uwsgi (or gunicorn) starts when multiple workers are forked from the first process.
If there is a request in the first process when it starts, then this opens a database connection and the connection is forked to the next process. But in the database, of course, no new connection is opened and a broken connection occurs.
You had to specify lazy: true, lazy-apps: true (uwsgi) or preload_app = False (gunicorn)
In this case, add. workers do not fork, but run themselves and open their normal connections themselves
简单概括就是uwsgi默认的preforking模式下,数据库连接可能从master被fork到worker,从而导致相应的连接失效。
解决
在项目的uwsgi配置文件中开启lazy-apps
模式。这种模式下uwsgi会首先fork,再在各个worker中加载app,而不是在master完成全部加载后再进行fork,从而避免在创建master process时就建立数据库连接。
# add this row into your own uwsgi.ini file
lazy-apps = true
有关uwsgi默认的这种preforking模式和其提供的lazy、lazy-apps两种设置的信息可以参考这篇很不错的文章《The Art of Graceful Reloading》Preforking VS lazy-apps VS lazy
更多推荐
所有评论(0)