【问题标题】:Python networking extremely slow [closed]Python网络非常慢[关闭]
【发布时间】:2012-10-29 08:56:22
【问题描述】:

我有两台服务器(让我将它们命名为 A 和 B)。

事实:

  • 它们具有相同的 CPU、内存、主板、硬盘驱动器、上行链路速度。
  • 它们都在带有 Python 2.7.3 和 Django 最新版本的 Ubuntu 12.04 上。
  • 它们还位于具有相同名称服务器设置的同一数据中心。
  • 它们具有与名称服务器相似的 ping 和 traceroute 结果。

服务器 A 工作正常。我的问题是使用python连接互联网时服务器B非常慢。

以下是我在两台服务器上进行的测试(domain_list_1 和 domain_list_2 是两个列表,每个列表中包含 100 个唯一域):

测试一:

starttime = time.time()
for domain in domain_list_1:
    ip = socket.gethostbyname(domain)
print '%.1f items per second' % (100/(time.time()-starttime))
>> Server A Results: 3.3 items per second
>> Server B Results: 0.7 items per second

测试二:

starttime = time.time()
for domain in domain_list_2:
    os.system('nslookup %s > /dev/null' % domain)
print '%.1f items per second' % (100/(time.time()-starttime))
>> Server A Results: 3.3 items per second
>> Server B Results: 3.3 items per second

从测试二中可以看出,服务器 B 上的网络没有问题。

我用 urllib2 做了类似的测试,结果是一样的(服务器 A 没问题,但服务器 B 使用 urllib2 比使用 wget 或 curl 来做同样的工作要慢)。所以我相信这是一个Python问题。我只是不知道服务器 B 上的 Python 设置出了什么问题。

有没有办法可以剖析内部流程并找出代码的哪一部分减慢了整个流程?

提前谢谢你!

【问题讨论】:

  • “连接到互联网”与您所做的非常不同,即“按名称查找 DNS 条目”。您的名称解析系统可能在服务器 B 上配置错误。这不太可能是 Python 问题,因为 Python 只是调用操作系统。
  • @Greg,如果OS级别的名称解析有问题,如何解释nslookup比Python的socket.gethostbyname()快得多?
  • nslookup 会绕过本地解析器库,因为它特定于 DNS(请记住,名称可以通过多种方式解析,其中只有一种是 DNS)。检查/etc/nsswitch.conf 以了解如何查找主机名。
  • @Greg, /etc/nsswitch.conf on A & B 完全一样。
  • 那么hosts: 的行是什么意思?该行列出的服务是解析器库检查主机名查找的内容。其中一个条目可能是dns,但可能还有其他条目(这可能会导致您的问题)。你也可以在strace 下运行你的程序,看看额外的延迟在哪里(但这样可能很难追踪)。

标签: python performance networking dns gethostbyname


【解决方案1】:

根据 Greg 给出的建议,我查看了 strace 的输出,发现如下:

服务器 A:

12879 21:29:24.182590 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("206.251.73.9")}, 16) = 0 <0.000035>
12879 21:29:24.182694 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}]) <0.000018>
12879 21:29:24.182778 sendto(5, "'!\1\0\0\1\0\0\0\0\0\0\njanadrakka\3com\0\0\1\0\1", 32, MSG_NOSIGNAL, NULL, 0) = 32 <0.000040>
12879 21:29:24.182881 poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}]) <0.067000>
12879 21:29:24.249987 ioctl(5, FIONREAD, [130]) = 0 <0.000022>
12879 21:29:24.250100 recvfrom(5, "'!\201\200\0\1\0\1\0\2\0\2\njanadrakka\3com\0\0\1\0\1"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("206.251.73.9")}, [16]) = 130 <0.000032>
12879 21:29:24.250287 close(5)          = 0 <0.000053>

服务器 B:

4850  21:28:55.501276 connect(5, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("206.251.73.9")}, 16) = 0 <0.000019>
4850  21:28:55.501348 poll([{fd=5, events=POLLOUT}], 1, 0) = 1 ([{fd=5, revents=POLLOUT}]) <0.000014>
4850  21:28:55.501419 sendto(5, "\346\10\1\0\0\1\0\0\0\0\0\0\fdeghatgostar\3com\0\0\1"..., 34, MSG_NOSIGNAL, NULL, 0) = 34 <0.000036>
4850  21:28:55.501506 poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}]) <0.615731>
4850  21:28:56.117335 ioctl(5, FIONREAD, [129]) = 0 <0.000033>
4850  21:28:56.117429 recvfrom(5, "\346\10\201\200\0\1\0\1\0\2\0\2\fdeghatgostar\3com\0\0\1"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("206.251.73.9")}, [16]) = 129 <0.000011>
4850  21:28:56.117499 close(5)          = 0 <0.000009>

此系统调用发生延迟:

答: 12879 21:29:24.182881 poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}] ) 0.067000>

B: 4850 21:28:55.501506 poll([{fd=5, events=POLLIN}], 1, 5000) = 1 ([{fd=5, revents=POLLIN}] ) 0.615731>

解决方案:

似乎延迟是由服务器 B 上的 IPv6 dns 查找引起的。但是,我仍然不确定为什么服务器 A 没有这样的问题,但在服务器 B 上进行的以下更改解决了它。

将以下行添加到 /etc/sysctl.conf 并重新启动服务器。

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

最后,感谢 Greg 的建议。

【讨论】:

    猜你喜欢
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-25
    相关资源
    最近更新 更多