Django, низкие запросы в секунду с воркерами gunicorn 4

Я пытаюсь понять, почему мой веб-сайт django (рабочие Gunicorn 4) работает медленно при большой нагрузке, я профилировал http://djangosnippets.org/snippets/186/ без четкого ответа, поэтому я начал несколько нагрузочных тестов с нуля, используя ab -n 1000 -c 100 http://localhost:8888/

Простой Httpreponse("hello world") без промежуточного ПО ==> 3600req/s

Простой Httpreponse("hello world") с промежуточным ПО (кешированный сеанс, кэшированная аутентификация) ==> 2300req/s

Простой render_to_response, который печатает только форму (кешированный шаблон) ==> 1200req/s (время отклика было разделено на 2)

Простой render_to_response с 50 запросами memcache ==> 157req/s

Запросы Memcache должны быть намного быстрее (я использую PyLibMCCache)? Является ли рендеринг шаблона таким же медленным, как этот результат?

Я пробовал разные методы профилирования без какого-либо успеха.

$ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 46936
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 400000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 46936
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

$ sysctl -p

fs.file-max = 700000
net.core.somaxconn = 5000
net.ipv4.tcp_keepalive_intvl = 30

Я использую ubuntu 12.04 (6 ГБ оперативной памяти, ядро ​​​​i5)

Любая помощь, пожалуйста?


person surfeurX    schedule 05.03.2013    source источник
comment
+1 за исследование, которое вы провели   -  person Private    schedule 05.03.2013
comment
Это зависит ... что вы делаете в представлениях? какие запросы вы выполняете? на чем ты их запускаешь?   -  person ionelmc    schedule 07.03.2013
comment
Ваш сервер memcached находится на той же машине или на внешней?   -  person Tommaso Barbugli    schedule 09.03.2013


Ответы (2)


Это действительно зависит от того, сколько времени требуется для выполнения запроса memcached и открытия нового соединения (django закрывает соединение по завершении запроса), и ваш worker, и memcached могут справиться с гораздо большей нагрузкой, но, конечно, если это займет 5/ 10 мс для вызова memcached, тогда 50 из них будут узким местом, поскольку у вас есть сетевая задержка, умноженная на количество вызовов.

Прямо сейчас вы просто тестируете django, gunicorn, свою машину и свою сеть.

Если на этом уровне у вас что-то не так, эти тесты не укажут вам на очень интересные открытия.

То, что замедляет работу вашего приложения, скорее всего, связано с тем, как вы используете свою базу данных и memcached (и, возможно, при рендеринге шаблона).

По этой причине я действительно предлагаю вам получить панель инструментов отладки django и посмотреть, что происходит на ваших реальных страницах.

Если окажется, что открытие соединения с memcached является узким местом, вы можете попробовать использовать пул соединений и оставить соединение открытым.

person Tommaso Barbugli    schedule 09.03.2013
comment
Я сделал все это (memcache-debug-panel, профилирование...), в основном я решил свою проблему, минимизировав запросы memcache и сохранив html-код непосредственно в memcache (потому что некоторые теги шаблона django также очень медленные). при этом я умножил r/s * 100 - person surfeurX; 09.03.2013

Вы можете исследовать производительность memcached.

$ python manage.py shell
>>> from django.core.cache import cache
>>> cache.set("unique_key_name_12345", "some value with a size representative of the real world memcached usage", timeout=3600)
>>> from datetime import datetime
>>> def how_long(n):
        start = datetime.utcnow()
        for _ in xrange(n):
            cache.get("unique_key_name_12345")
        return (datetime.utcnow() - start).total_seconds()

С таким тестом туда и обратно я вижу, что 1 поиск в memcached займет около 0,2 мс на моем сервере.

Проблема с django.core.cache и pylibmc заключается в том, что функции блокируются. Потенциально вы можете получить в 50 раз больше этого числа за HTTP-запрос туда и обратно. 50 раз по 0,2 мс это уже 10 мс.

Если вы достигли 1200 запросов/с на 4 рабочих процессах без memcached, среднее время приема-передачи HTTP составило 1/(1200/4) = 3,33 мс. Добавьте к этому 10 мс, и получится 13,33 мс. Пропускная способность с 4 работниками упадет до 300 запросов в секунду (что примерно соответствует вашему числу 157).

person Freek Wiekmeijer    schedule 29.01.2014