Запуск Python в проекте Django, который взаимодействует с различными веб-сервисами, у нас есть проблема, из-за которой иногда запросы занимают около 5 секунд вместо их обычных < 100 мс.
Я сократил это до времени, проведенного в функции socket.getaddrinfo
- это называется requests
, когда мы подключаемся к внешним службам, но также, по-видимому, влияет на соединение Django по умолчанию с полем базы данных Postgres в кластер. Когда мы перезапускаем uwsgi
после развертывания, первые запросы, которые входят в систему, занимают 5 секунд, чтобы отправить ответ. Я также считаю, что наши задачи сельдерея занимают 5 секунд на регулярной основе, но я еще не добавил слежение за ними в statsd.
Я написал код для воспроизведения проблемы:
import socket
import timeit
def single_dns_lookup():
start = timeit.default_timer()
socket.getaddrinfo('stackoverflow.com', 443)
end = timeit.default_timer()
return int(end - start)
timings = {}
for _ in range(0, 10000):
time = single_dns_lookup()
try:
timings[time] += 1
except KeyError:
timings[time] = 1
print timings
Типичные результаты: {0: 9921, 5: 79}
Мой коллега уже указал на возможные проблемы вокруг времени поиска ipv6 и добавил это к /etc/gai.conf
:
precedence ::ffff:0:0/96 100
Это определенно улучшило поиск из не-Python-программ, таких как curl
, которые мы используем, но не из самого Python. В ящиках сервера работает Ubuntu 16.04.3 LTS, и я могу воспроизвести это на ванильной виртуальной машине с Python 2.
Какие шаги я могу предпринять для повышения производительности всех поисков Python, чтобы они могли принимать < 1s?