5

将我的 Django 1.6 应用程序升级到 Django 1.7 后,我在从 PostgreSQL 获取数据时开始出现随机错误:

DatabaseError: server sent data ("D" message) without prior row description ("T" message)
lost synchronization with server: got message type "�", length -1244613424

DatabaseError: lost synchronization with server: got message type "0", length 842674226

ProgrammingError: no results to fetch

ValueError: invalid literal for int() with base 10: 'feuj3f47jvsdv7tgnj43g63j'

当我在浏览器中快速打开 10 个选项卡时,一半的选项卡正常加载,其中一半出现 DB 错误。当我刷新发生错误的选项卡时,它们会正常加载。

我通过uwsgi和nginx运行Django,psycopg2的版本是2.5.4。

总体而言,与 Postgres 的通信似乎以某种方式完全中断,并且不同查询的结果混合在一起。


编辑:

经过几个小时的故障排除后,我发现了以下内容:

Django 1.6 +
uwsgi - 工作 Django 1.7 + gunicorn - 工作
Django 1.7 + uwsgi - 不工作,引发数据库错误。所以问题似乎出在特别是 uwsgi 和 Django 1.7 的组合上。这很奇怪,我有另一个 Django 1.7 项目在具有相同 uwsgi 的同一台服务器上运行,它没有问题。

有任何想法吗?

(我真的不介意切换到 gunicorn,可能不得不走这条路,但为什么会发生这种情况仍然很有趣)


更新 2:仔细检查显示 Django 内部发生了完全疯狂的事情,比如模型的主键被当前用户的 session_id 替换(这是“invalid literal for int() with base 10”错误的来源)和 Django 向 DB 发出查询“忘记" 来指定 WHERE 子句。我可能会称之为某种内存损坏。


更新 3:我们从 uwsgi 切换到 gunicorn,问题现在消失了。一切都很好。不过,我可能仍在寻找合适的解决方案。

4

1 回答 1

6

我认为lazy-apps=true应该做的伎俩。来自 uwsgi 文档:

uWSGI 尽可能尝试(ab)使用 fork() 调用的 Copy On Write 语义。默认情况下,它会在加载您的应用程序以共享尽可能多的内存后分叉。如果由于某种原因不希望出现这种行为,请使用惰性应用程序选项。这将指示 uWSGI 在每个 worker 的 fork() 之后加载应用程序。请注意,有一个名为lazy 的旧选项更具侵入性并且非常不鼓励(它仍然在这里只是为了向后兼容)

如果您不打开lazy-apps,worker 将共享内存,并且很可能会破坏它:

模型的主键被当前用户的 session_id 替换。

当涉及到连接和东西时,不设置lazy-apps是危险的。

缺点是每个工作人员都会有一个完整的连接池(如果发生连接池),您最终可能会使用大量连接。

我不是 python 专家,但我认为使用 gevent 之类的东西以集中方式处理连接池。你可能甚至不需要lazy-apps.

于 2015-03-27T20:24:30.290 回答