-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Client timing out when coroutines making requests in async_timeout block are run together #3457
Comments
GitMate.io thinks the contributor most likely able to help you is @asvetlov. Possibly related issues are #3291 (Websocket client hanging/blocking?), #1142 (Can't make 40k requests from client to server), #3251 (Aiohttp Client request limit), #1180 (Client request timeout should be optional), and #22 (Make client tracebacks more useful.). |
This doesn't look like a bug to me. |
I assume the From what I can understand, the confusion is that the request hits the timeout due to the heavy workload in another task, rather than anything to do with the network request. I think this is just the way the timeout is implemented and I'm not sure if it should behave differently. A workaround might be to use |
Same problem. I believe the "timeouts" work just by checking how much time has passed from the task (request in our case) start. And if we have some another blocking (cpu-consuming) task running in parallel, it can cause the timeout in the first one despite the request itself was fast. I don't know if there any possibility to count the real sock-read time though. Working on it... |
import asyncio
import time
from aiohttp import web, ClientSession, ClientTimeout
routes = web.RouteTableDef()
@routes.get('/')
async def hello(request):
await asyncio.sleep(1)
return web.Response(text="Hello, world")
app = web.Application()
app.add_routes(routes)
async def start_server():
runner = web.AppRunner(app)
await runner.setup()
site = web.TCPSite(runner, 'localhost', 9090)
await site.start()
async def make_request():
print('making request...')
timeout = ClientTimeout(sock_connect=3, sock_read=3)
async with ClientSession(timeout=timeout) as sess:
async with sess.get('http://localhost:9090/') as resp:
await resp.text()
print('got response!')
async def blocking():
time.sleep(3)
async def main():
asyncio.create_task(start_server())
asyncio.create_task(make_request())
await asyncio.sleep(1)
asyncio.create_task(blocking())
await asyncio.sleep(5)
asyncio.run(main()) PoC. The topic starter used just |
Blocking event loop for a relatively (e.g., more than 10-100 milliseconds) long time violates asyncio usage rules. Please put such code in |
Indeed, this was what I was trying to explain in my previous comment. Another option is to break up the workload using
|
Long story short
I have a coroutine which makes an async request inside of a timeout block and then performs a slow synchronous process with the returned data. When I run this process twice in parallel the request times out after the first process completes and the context switches to the other request.
This issue only happens about half the time I run the test script included in the Steps to Reproduce section, and I haven't been able to figure out why.
Expected behaviour
I would expect both processes to finish successfully.
Actual behaviour
In the script below, both processes enter the
async with session.get(url) as response:
block and execute the lineawait response.text()
. The first process downloads the data and spends longer than the timeout processing the data. The context then switches back to the other request and attempts to download the data but raises aTimeoutError
Steps to reproduce
Your environment
Using aiohttp client
Python 3.6.5
aiohttp==3.4.4
Ubuntu 18.04.1 LTS
Note
In my actual code I'm using one session per request with a single connector per application. This seems to make the issue occur every time. I'm aware that the documentation recommends one session per application, but the justification that this is so that all requests use the same connection pool makes me think that what I am doing is fine. Let me know if I'm missing something.
Test script using multiple sessions
This script results in the exact same output as seen in the Actual behaviour section, again only about half the time.
The text was updated successfully, but these errors were encountered: