Python`socket.getaddrinfo`占用了大约0.1%的请求5秒

jam*_*esc 12 python sockets dns python-requests

在与各种Web服务进行通信的Django项目上运行Python,我们遇到一个问题,偶尔请求大约需要5秒而不是通常的<100毫秒.

我把这个缩小到了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
Run Code Online (Sandbox Code Playgroud)

典型的结果是 {0: 9921, 5: 79}

我的同事已经指出了围绕ipv6查找时间的潜在问题,并将其添加到/etc/gai.conf:

precedence ::ffff:0:0/96  100
Run Code Online (Sandbox Code Playgroud)

这肯定改进了curl我们使用的非Python程序的查找,但不是来自Python本身.服务器盒正在运行Ubuntu 16.04.3 LTS,我可以在Python 2的vanilla虚拟机上重现这一点.

我可以采取哪些步骤来提高所有Python查找的性能,使它们可以<1s?

Krz*_*arz 10

5s是DNS查找的默认超时.

你可以降低它.

你真正的问题可能是(无声)UDP数据包丢失在网络上.

编辑:通过TCP进行分辨率试验.从未这样做过.可能会帮助你.