如何使用 aiohttp 处理 DNS 超时?

Wil*_*lem 4 python dns python-3.x python-asyncio aiohttp

aiohttp自述文件说:

如果您想对 aiohttp 客户端使用超时,请使用标准 asyncio 方法:yield from asyncio.wait_for(client.get(url), 10)

但这并不能处理 DNS 超时,我猜这是由操作系统处理的。而且with aiohttp.Timeout不处理操作系统 DNS 查找。

在asyncio repo上进行了讨论,但没有最终结论,Saghul 已经制作了aiodns,但我不确定如何将其混合到 aiohttp 中以及是否允许asyncio.wait_for功能。

测试用例(在我的 Linux 机器上需要 20 秒):

async def fetch(url):
    url = 'http://alicebluejewelers.com/'
    with aiohttp.Timeout(0.001):
        resp = await aiohttp.get(url)
Run Code Online (Sandbox Code Playgroud)

And*_*lov 5

Timeout按预期工作,但不幸的是您的示例挂在 python 关闭过程上:它等待执行 DNS 查找的后台线程的终止。

作为解决方案,我建议使用aiodns手动 IP 解析:

import asyncio
import aiohttp
import aiodns

async def fetch():
    dns = 'alicebluejewelers.com'
    # dns = 'google.com'
    with aiohttp.Timeout(1):
        ips = await resolver.query(dns, 'A')
        print(ips)
        url = 'http://{}/'.format(ips[0].host)
        async with aiohttp.get(url) as resp:
            print(resp.status)

loop = asyncio.get_event_loop()
resolver = aiodns.DNSResolver(loop=loop)
loop.run_until_complete(fetch())
Run Code Online (Sandbox Code Playgroud)

也许解决方案值得作为可选功能包含在 TCPConnector 中。

欢迎拉请求!

  • 对于 Google 员工,这已在 aiohttp 中实现:请参阅 https://github.com/KeepSafe/aiohttp/pull/819 (2认同)