破译 psycopg2:OperationalError 的特例

Deciphering a special case of psycopg2:OperationalError

我有一个带有 postgresql 后端的 Django 网络应用程序,用户可以在其中聚集并互相发送消息。这些消息可以被赞成或反对。如果有任何滥用,有很多反对票的人会得到“ghost banned”(在我的网站上称为地狱禁令)。

为此,我有一个简单的中间件来检查用户是否被禁止:

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
from myapp.models import HellBanList

class HellBannedMiddleware(object):

    def process_request(self, request):
        if request.user.is_authenticated():
            request.user_banned = HellBanList.objects.filter(condemned=request.user).exists()
        else:
            request.user_banned = 0

根据中间件returns,我在网站上进行了一些操作。

我使用 newrelic 来监控我的应用程序。间歇性地,我看到一个错误突然出现。我需要帮助来破译这个以及我可以采取什么步骤来处理它。如下:

psycopg2:OperationalError

/myproject.middleware.HellBanned:HellBannedMiddleware.process_request

Error message

psycopg2:OperationalError: could not translate host name "mywebapp.cloudapp.net" to address: Name or service not known 

完整的堆栈跟踪如下:

Stack trace
Traceback (most recent call last):
File "/home/myuser/.virtualenvs/myenv/bin/gunicorn", line 11, in <module>
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 74, in run
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 189, in run
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/app/base.py", line 72, in run
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 181, in run
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 477, in manage_workers
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 540, in spawn_workers
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py", line 507, in spawn_worker
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py", line 124, in init_process
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 119, in run
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 66, in run_for_one
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 30, in accept
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 130, in handle
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 176, in handle_request
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/web_transaction.py", line 704, in __iter__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/api/web_transaction.py", line 1080, in __call__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 255, in __call__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 92, in get_response
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/hooks/framework_django.py", line 228, in wrapper
File "/home/myuser/myfolder/myproject/middleware/HellBanned.py", line 8, in process_request
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/utils/functional.py", line 202, in inner
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/utils/functional.py", line 268, in _setup
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/contrib/auth/middleware.py", line 18, in <lambda>
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/contrib/auth/middleware.py", line 10, in get_user
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/contrib/auth/__init__.py", line 134, in get_user
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 46, in __getitem__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 168, in _get_session
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/user_sessions/backends/db.py", line 32, in load
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 143, in get
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/query.py", line 382, in get
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/query.py", line 90, in __len__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/query.py", line 301, in iterator
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 775, in results_iter
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 839, in execute_sql
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/backends/__init__.py", line 326, in cursor
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 182, in _cursor
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/newrelic-2.56.0.42/newrelic/hooks/database_dbapi2.py", line 102, in __call__
File "/home/myuser/.virtualenvs/myenv/local/lib/python2.7/site-packages/psycopg2/__init__.py", line 164, in connect

仔细一看,我的地狱禁止中间件第8行有个错误,正好是这样的:if request.user.is_authenticated():

这个错误就像我说的那样间歇性地出现。上次我看到一串这样的错误是在导致我的网站崩溃的 disk full 错误之后的几个小时,尽管我也看到它以其他方式弹出。

任何人都可以解释一下这是什么,以及我如何为遇到此问题的不幸用户处理错误?提前致谢。

背景

您似乎在 mywebapp.cloudapp.net 上托管了一个 postgresql 数据库,它的端口 (5432) 对 public 开放。这不是最佳做法。通常,出于安全原因,您应该只在专用网络 IP 上公开数据库。其次,连接到远程位置的数据库意味着您将为每个查询添加 20-30 毫秒到数百毫秒的任何内容。如果您获取大量数据,延迟可能以秒为单位。

更糟糕的是,您使用的是服务器的 FQDN 而不是 IP 地址。这意味着每个请求还涉及 DNS 解析。除非 DNS 请求在本地缓存,否则可能会额外增加 20-30 毫秒的开销。而且你也运行进入你刚刚做的问题!

临时解决方案:

为避免您的站点因 DNS 解析问题而失败,请找到服务器的 IP 地址并在您的 django settings.py 中使用它而不是主机名。