You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Asyncio HTTP Server无法并发处理请求的原因及解决方法

问题原因分析

你用的asyncio.start_server本身是支持并发处理多个连接的——每有一个新连接建立,事件循环就会创建独立任务来运行handle_echo协程。之所以看到请求被串行处理,问题出在测试方式和服务器协议不匹配:

  • 浏览器的HTTP连接限制:浏览器对同一域名的HTTP连接有并发数限制(比如Chrome默认最多6个),且HTTP/1.1默认启用keep-alive复用连接。你在两个标签页发请求时,浏览器可能会等第一个请求的连接关闭后,才发送第二个请求,导致服务器看起来是串行处理。
  • 非标准HTTP服务器:你的代码是TCP回显服务器,不是标准HTTP服务器。浏览器发送完整的HTTP请求,但服务器只是原样回显,浏览器无法识别响应,会一直保持连接等正确结果,进一步导致后续请求只能串行等待。
解决方法

1. 用正确工具测试并发

别用浏览器测试,改用命令行工具在多个终端同时发起TCP请求,比如nc(netcat):
第一个终端执行:

echo "test1" | nc 127.0.0.1 8888

第二个终端立即执行:

echo "test2" | nc 127.0.0.1 8888

此时服务器会输出并发处理的日志:

Enter echo handler
Enter my long running task
Enter echo handler
Enter my long running task
Finished my long running task
Exit echo handler
Finished my long running task
Exit echo handler

2. 改为标准asyncio HTTP服务器

如果需要处理HTTP请求,用aiohttp(Python主流异步HTTP库)更合适,示例代码:

import asyncio
from aiohttp import web

async def handle(request):
    print("Enter HTTP handler")
    await asyncio.sleep(10)
    print("Finished long task")
    return web.Response(text="Hello, world")

async def main():
    app = web.Application()
    app.add_routes([web.get('/', handle)])
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, '127.0.0.1', 8888)
    await site.start()
    print("Serving on http://127.0.0.1:8888")
    await asyncio.Event().wait()

asyncio.run(main())

此时用多个浏览器标签页或curl测试,就能看到并发处理的效果。

3. 修改现有TCP服务器,让浏览器正确关闭连接

如果想继续用现有TCP服务器,需要返回浏览器能识别的HTTP响应,让它主动关闭连接:
修改handle_echo函数:

async def handle_echo(reader, writer):
    print("Enter echo handler")
    data = await reader.read(100)
    message = data.decode()
    addr = writer.get_extra_info("peername")

    print("Enter my long running task")
    await asyncio.sleep(10)
    print("Finished my long running task")

    # 返回标准HTTP响应,触发浏览器关闭连接
    response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello"
    writer.write(response)
    await writer.drain()

    writer.close()
    await writer.wait_closed()  # 等待连接关闭完成
    print("Exit echo handler")

此时浏览器能正确解析响应并关闭连接,后续请求就能建立新连接并发处理。

内容的提问来源于stack exchange,提问作者Peter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:22:04