在與各種網絡服務通信的Django項目上運行Python,我們遇到一個問題,偶爾請求花費約5秒而不是通常的時間< 100 ms 。Python`socket.getaddrinfo`花費5秒約0.1%的請求
我把這個縮小到了socket.getaddrinfo
函數的時間 - 當我們連接到外部服務時,這個函數被requests
調用,但它似乎也會影響集羣中Postgres數據庫框的默認Django連接。當我們在部署之後重新啓動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
w這是我們使用的,但不是來自Python本身。服務器機器運行的是Ubuntu 16.04.3 LTS,我可以用Python 2在vanilla VM上重現這一點。
我可以採取哪些措施來提高所有Python查找的性能,以便他們可以採取< 1秒?
如何緩存結果並使用芹菜或類似的東西更新它們? –
聽起來像你的dns解析器很慢,給ncsd一個試試嗎? – georgexsh
@YaroslavSurzhikov你對緩存有什麼建議?你會如何建議緩存應該更新並保持熱點,以便Python服務器代碼*從不*必須運行緩慢的請求,除非更新緩存? – jamesc