Python中使用socket进行DNS缓存,为什么速度反而变慢了呢?

查了一下网上关于socket关于dns缓存的代码,希望提高网络请求的速度,
自己在代码中使用了以后,发现速度反倒慢了,为什么呢 下面的 100 个请求中,使用了缓存之后时间增加了 4 秒多, 10 个请求的时候,时间增加了 0.2 秒左右

# coding=utf-8
import requests
import time
import socket
_dnscache = {}

def _setDNSCache(): “”" DNS 缓存 “”" def _getaddrinfo(*args, **kwargs): if args in _dnscache: # print (str(args) + " in cache") return _dnscache[args] else: # print (str(args) + " not in cache") _dnscache[args] = temp_getaddrinfo(*args, **kwargs) return _dnscache[args]

if not hasattr(socket, '_getaddrinfo'):
    temp_getaddrinfo = socket.getaddrinfo
    socket.getaddrinfo = _getaddrinfo

class TiebaSpider: def init(self,tieba_name): self.tieba_name = tieba_name self.headers = { “User-Agent”:“Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36” } def get_url_list(self): url_temp = “https://tieba.baidu.com/f?kw=” + self.tieba_name + “&ie=utf-8&pn={}” url_list = [url_temp.format(i*50) for i in range(100)] return url_list

def parse_url(self,url):
    print("now parsing url",url)
    response = requests.get(url,headers=self.headers)
    return response.content.decode()

def run(self):
    url_list = self.get_url_list()
    for url in url_list:
        html_str = self.parse_url(url)

if name == ‘main’: t1 = time.time() _setDNSCache() tieba_spider = TiebaSpider(“李毅”) tieba_spider.run() print(time.time()-t1)


Python中使用socket进行DNS缓存,为什么速度反而变慢了呢?

4 回复

你是不是应该先测试一下缓存命中率


我看了你的问题,在Python里用socket做DNS缓存反而变慢,这挺常见的。核心问题通常是缓存实现方式不对,或者没处理好并发。

最常见的问题是用了同步socket,每次DNS查询都会阻塞整个线程。比如你这样写:

import socket
from functools import lru_cache

@lru_cache(maxsize=128)
def get_ip(hostname):
    try:
        return socket.gethostbyname(hostname)
    except socket.error:
        return None

这个缓存确实能避免重复查询,但第一次查询还是会阻塞。更糟糕的是,如果多个线程同时查不同的域名,它们会被顺序执行,因为lru_cache是线程安全的但会加锁。

真正的问题是DNS查询本身是I/O操作,应该用异步方式。但如果你坚持要用缓存加速,可以试试预加载缓存,或者在程序启动时批量解析需要的域名。

另一个可能是DNS服务器响应慢,或者你缓存了错误的TTL值。不过从你的描述看,更像是同步阻塞导致的性能问题。

建议用异步DNS客户端库。

除了第一个请求,后续的请求应该的都是命中缓存的。
不过百度服务器毕竟不是放在你旁边,同样的 URL 每次的网络耗时都是不同的,所以这样用来对比是没啥意义的。

我的感觉瓶颈不在 DNS,建议使用 https://github.com/rkern/line_profiler 这个工具来分析一下每行代码的耗时,这样就能找出瓶颈了。

这个 dns 缓存意义不大,系统本来就有一层 dns 缓存。我猜换成 session 会快很多,时间都花在 ssl 隧道和 tcp 握手

回到顶部