Uruchamiając Pythona na projekcie Django, który komunikuje się z różnymi usługami sieciowymi, mamy problem, który czasami wymaga około 5 sekund zamiast zwykłego < 100 ms .Python `socket.getaddrinfo` trwa 5 sekund około 0,1% żądań
Zawęziłem to do czasu podjętego w funkcji socket.getaddrinfo
- jest to wywoływane przez requests
, kiedy łączymy się z usługami zewnętrznymi, ale wydaje się również, że wywołuje ono domyślne połączenie Django z polem bazy danych Postgres w klastrze. Po ponownym uruchomieniu uwsgi
po wdrożeniu pierwsze przychodzące żądania będą wymagać 5 sekund na wysłanie odpowiedzi. Uważam również, że nasze zadania związane z selerem trwają 5 sekund, ale nie dodałem jeszcze do nich śledzenia statystyk.
Pisałem jakiś kod, aby odtworzyć problem:
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
Typowe wyniki {0: 9921, 5: 79}
Mój kolega już wskazał na potencjalne problemy wokół czasach IPv6 odnośników i dodał to do /etc/gai.conf
:
precedence ::ffff:0:0/96 100
To zdecydowanie poprawiła wyszukiwań z programów nie Pythona, takich jak curl
wag Używamy go, ale nie z samego Pythona. Skrzynki serwerów są wyposażone w Ubuntu 16.04.3 LTS i mogę odtworzyć to na wanilii VM z Pythonem 2.
Co mogę zrobić, aby poprawić wydajność wszystkich wyszukiwań w Pythonie, aby mogły one pobierać < 1s ?
Co powiesz na buforowanie wyników i odnowienie ich przy użyciu selera lub coś w tym stylu? –
brzmi jak twój resolwent dns jest powolny, daj spróbować ncsd? – georgexsh
@YaroslavSurzhikov Co zasugerowałbyś w pamięci podręcznej?A jak zasugerowałbyś, że pamięć podręczna powinna być aktualizowana i utrzymywana w stanie gorącym, aby kod serwera Python * nigdy * nie musiał uruchamiać powolnego żądania, z wyjątkiem aktualizacji pamięci podręcznej? – jamesc