带有 uWSGI 的 Django 中 Geoip2() 上的“[Errno 12] 无法分配内存”

Posted

技术标签:

【中文标题】带有 uWSGI 的 Django 中 Geoip2() 上的“[Errno 12] 无法分配内存”【英文标题】:"[Errno 12] Cannot allocate memory" on Geoip2() in Django with uWSGI 【发布时间】:2017-12-06 21:26:41 【问题描述】:

以下代码在manage.py shell运行成功:

from django.contrib.gis.geoip2 import GeoIP2
g = GeoIP2()

如果我使用manage.py runserver 手动启动服务器 并将代码放在我的 Django 视图中,它也运行良好。

我的 Django 应用程序使用 uWSGInginx 作为反向代理托管。 uWSGINginx 都使用 www-data 用户运行。

这是我在uWSGI 上运行时遇到的异常:

...
File "/home/myuser/Env/virtenv/myproject/index/views.py" in index
  28.     g = GeoIP2()

File "/home/myuser/Env/virtenv/local/lib/python2.7/site-packages/django/contrib/gis/geoip2/base.py" in __init__
  95.                 self._city = geoip2.database.Reader(city_db, mode=cache)

File "/home/myuser/Env/virtenv/local/lib/python2.7/site-packages/geoip2/database.py" in __init__
  82.         self._db_reader = maxminddb.open_database(filename, mode)

File "/home/myuser/Env/virtenv/local/lib/python2.7/site-packages/maxminddb/__init__.py" in open_database
  37.         return maxminddb.reader.Reader(database, mode)

File "/home/myuser/Env/virtenv/local/lib/python2.7/site-packages/maxminddb/reader.py" in __init__
  52.                     db_file.fileno(), 0, access=mmap.ACCESS_READ)

Exception Type: error at /
Exception Value: [Errno 12] Cannot allocate memory

局部变量是:

Variable    Value
database    '/home/myuser/Env/virtenv/myproject/geoip/GeoLite2-City.mmdb'
db_file     <closed file '/home/myuser/Env/virtenv/myproject/geoip/GeoLite2-City.mmdb',     mode 'rb' at 0x7f8c5cf5d390>
mode        0
self        <maxminddb.reader.Reader object at 0x7f8c5cf5f550>

我使用 Virtualbox,我的客户操作系统是 Ubuntu 16.04。我在那里有 4GB 交换文件。 如果我释放一些 RAM,问题仍然存在。 不过,这不应该是操作系统级别的内存问题, 因为我可以在 shell 中创建 GeoIP2 对象,也可以手动运行服务器。

接下来我检查的是我项目中的 geoip 目录归 www-data 所有,并且有 775 个。 里面的两个文件(GeoLite2-City.mmdbGeoLite2-Country.mmdb)也归 www-data 所有,有 774 个。

/etc/systemd/system/uwsgi.service 包含:

[Unit]
Description=uWSGI Emperor service

[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown www-data:www-data /run/uwsgi'
ExecStart=/usr/local/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target

/etc/uwsgi/sites/my_site.ini 包含:

[uwsgi]

project = myproject
base = /home/myuser
home = %(base)/Env/virtenv/%(project)

binary-path = /usr/local/bin/uwsgi
chdir = %(home)
chmod-socket = 660
chown-socket = www-data:www-data
#emperor = true
#enable-threads = true
gid = www-data
limit-as = 1024
logto = /tmp/uwsgi.log
master = true
module = myproject.wsgi:application
pidfile = /opt/logs/uwsgi/master.pid
# number of cores on machine
processes = 2
python-path = %(home)
py-autoreload = 2
socket = /run/uwsgi/%(project).sock
uid = www-data
vacuum = true
virtualenv = %(base)/Env/virtenv
vhost = true
workers = 4

env = AWS_KEY=***************
env = AWS_SECRET=***************
env = DJANGO_SETTINGS_MODULE=myproject.settings.local
env = GMAIL_PASS=***************
env = PSQL_PASS=***************
env = SECRET_KEY=*********************************************

我想知道uWSGI的限制在哪里?

【问题讨论】:

你能用 htop 之类的东西监控虚拟机的内存使用情况吗? 我用 htop 检查过,我还剩 1.5GB 可用 RAM 【参考方案1】:

uWSGI 的ini 文件中的limit-as = 512 是罪魁祸首。将其加倍为1024 mb 即可解决问题。

来自官方 uWSGI 2 文档here:

限制为

参数:数字

限制进程地址空间 (vsz)(以兆字节为单位)。

限制每个 uWSGI (worker) 进程的地址空间使用 POSIX/UNIX setrlimit()。例如,limit-as 256 将不允许 uWSGI 进程增长超过 256MB 的地址空间。地址空间是 进程可以访问的虚拟内存。它不对应 物理内存。在启用此功能之前阅读并理解此页面 选项:http://en.wikipedia.org/wiki/Virtual_memory

【讨论】:

以上是关于带有 uWSGI 的 Django 中 Geoip2() 上的“[Errno 12] 无法分配内存”的主要内容,如果未能解决你的问题,请参考以下文章

Nginx、uwsgi、django、ubuntu 16 带有静态文件的问题

带有 Nginx 和 uWSGI 的 Django CDN

Amazon EC2 上带有 Nginx + uWSGI 的 Django 应用程序

Apache , uwsgi , django 查找时间

GeoIP + Django,无效的 GeoIP 城市数据文件

带有 Nginx 的 Django 的 build_absolute_uri 中的 localhost