Description
Describe the bug
I've been using aiohttp with FastAPI server without any major problems, however, several times a week it happens that the client fails to respect request timeout.
This snippet is 100% accurate to what I have in the production code.
from time import perf_counter
from aiohttp import ClientSession, ClientTimeout
async def requets():
timer = perf_counter()
try:
session = ClientSession(timeout=ClientTimeout(total=60, connect=10, sock_connect=10, sock_read=30))
response = await session.request('POST', url='/', json={})
response.raise_for_status()
return await response.json()
finally:
print(f'took {perf_counter() - timer:.3f}s')
Most of the time, the communication works perfectly. Having client and server machines in the same rack, req/response takes milliseconds. However, there seems to be a (nightly) period of (possible?) maintenance. In that case I can see in logs that response took well over 2 hours.
took 0.853s
took 419.666s
took 5052.691s
took 7462.243s
There are dozens of requests from a single process directed to the server at the same time. The requests do succeed, however, third of them finishes under second, while the rest takes minutes or hours to complete. From the server logs and actions I know the request arrived to FastAPI server immediately, while the response takes the whole time.
The question is, why the client doesn't respect 60s total timeout that I set?
I've tested timeouts on a mock server and client and it indeed did work. Is it possible that under some circumstances the client receives data slowly and fails to respect the timeout?
Under which case is the timeout not respected? I.e. is there a way to set total timeout that hits no matter what? (I mean except for anyio cancelling groups).
To Reproduce
I wasn't able to reproduce the problem in controlled environment, however, this is a repeating problem in a period of many weeks and like caused some maintenance on the machine.
Expected behavior
To be able to set timeout that always hits no matter what.
Logs/tracebacks
please, check the explanation
Python Version
$ python --version
Python 3.12.7
aiohttp Version
$ python -m pip show aiohttp
Name: aiohttp
Version: 3.10.10
Summary: Async http client/server framework (asyncio)
Home-page: https://github.com/aio-libs/aiohttp
Author:
Author-email:
License: Apache 2
Location: /apps/qminers/conda/envs/shared/lib/python3.12/site-packages
Requires: aiohappyeyeballs, aiosignal, attrs, frozenlist, multidict, yarl
Required-by:
multidict Version
$ python -m pip show multidict
Name: multidict
Version: 6.1.0
Summary: multidict implementation
Home-page: https://github.com/aio-libs/multidict
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache 2
Location: /apps/qminers/conda/envs/shared/lib/python3.12/site-packages
Requires:
Required-by: aiohttp, yarl
propcache Version
$ python -m pip show propcache
Name: propcache
Version: 0.2.0
Summary: Accelerated property cache
Home-page: https://github.com/aio-libs/propcache
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache-2.0
Location: /apps/qminers/conda/envs/shared/lib/python3.12/site-packages
Requires:
Required-by: yarl
yarl Version
$ python -m pip show yarl
Name: yarl
Version: 1.14.0
Summary: Yet another URL library
Home-page: https://github.com/aio-libs/yarl
Author: Andrew Svetlov
Author-email: [email protected]
License: Apache-2.0
Location: /apps/qminers/conda/envs/shared/lib/python3.12/site-packages
Requires: idna, multidict, propcache
Required-by: aiohttp
OS
Linux, RHEL 7, x86_64
Related component
Client
Additional context
No response
Code of Conduct
- I agree to follow the aio-libs Code of Conduct