Критическая ошибка сервера aiohttp при обрыве связи с клиентами

Есть aiohttp сервер. К нему идет очень большое количество запросов с клиента. В случае, если связь между клиентом и сервером резко обрывается, сервер может остановиться с ошибкой:

Task exception was never retrieved
future: <Task finished name='Task-45565' coro=<IocpProactor.accept.<locals>.accept_coro() done, defined at D:\Python\Python_3_8_2\lib\asyncio\windows_events.py:559> exception=OSError(22, 'Указанное сетевое имя более недоступно', None, 64, None)>
Traceback (most recent call last):
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 562, in accept_coro
    await future
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 808, in _poll
    value = callback(transferred, key, ov)
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 551, in finish_accept
    ov.getresult()
OSError: [WinError 64] Указанное сетевое имя более недоступно
Accept failed on a socket
socket: <asyncio.TransportSocket fd=604, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('0.0.0.0', 80)>
Traceback (most recent call last):
  File "D:\Python\Python_3_8_2\lib\asyncio\proactor_events.py", line 801, in loop
    conn, addr = f.result()
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 562, in accept_coro
    await future
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 808, in _poll
    value = callback(transferred, key, ov)
  File "D:\Python\Python_3_8_2\lib\asyncio\windows_events.py", line 551, in finish_accept
    ov.getresult()
OSError: [WinError 64] Указанное сетевое имя более недоступно

Код сервера:

from aiohttp import web

async def page(request):
    return web.Response(text='OK')

app = web.Application()
app.router.add_route('*', '/', page)
web.run_app(app, port=80)

Код клиента:

import asyncio
import aiohttp

async def do_get(url):
    while True:
        try:
            await asyncio.sleep(1)
            async with aiohttp.ClientSession() as session:
                async with session.get(url) as resp:
                    data = await resp.text()
                    print(data)
        except Exception as ex:
            print('Exception:', ex)

async def client():
    workers = 5000
    tasks = [asyncio.Task(do_get('http://127.0.0.1')) for i in range(workers)]
    await asyncio.gather(*tasks)

asyncio.run(client())

Для воспроизведения ошибки нужно запустить сервер, затем запустить клиент и через ~10 сек. завершить клиент. Ошибка в сервере появляется не всегда, возможно понадобится перезапустить клиент 3-7 раз. При этом на стороне сервера я никак не могу отловить это состояние и не знаю как его предотвратить или перезапустить сервер.

ОС: Windows 10 Python: 3.8.2 aiohttp: 3.6.2


Ответы (1 шт):

Автор решения: Evgeniy

Попробуй так:

from aiohttp import web

async def page(request):
    try:
        return web.Response(text='OK')
    except OSError:
        return None

app = web.Application()
app.router.add_route('*', '/', page)
web.run_app(app, port=80)

Т.е. просто игнорировать ошибку, как вариант

→ Ссылка