HTTPX异步性能表现如何

wen python案例 1

本文目录导读:

HTTPX异步性能表现如何

  1. 核心优势:基于优秀底层
  2. 性能对比:HTTPX vs aiohttp vs requests
  3. 实际性能影响因素
  4. 代码示例:100 个并发请求性能测试
  5. 总结:HTTPS 异步性能表现

HTTPX 是一个支持异步的 HTTP 客户端库,其异步性能表现非常优秀,但具体表现取决于你如何使用它。

HTTPX 的异步性能与著名的 aiohttp 相当,甚至在某些场景下更优,同时提供了更现代、更简洁的 API 和更丰富的功能。

下面我们从几个维度详细分析 HTTPX 的异步性能表现:

核心优势:基于优秀底层

  • 底层依赖:HTTPX 的异步后端完全基于 anyio (通过 httpcore 库实现)。anyio 是一个强大的异步底层库,它提供了与 asyncio(Python 原生异步库)和 trio 这两个异步框架的兼容性。
  • 传输层httpcore 负责底层的连接池、连接复用、超时控制等,这些是影响并发性能的关键,HTTPX 在连接池管理、复用、超时方面做得非常成熟和高效。

性能对比:HTTPX vs aiohttp vs requests

这是大家最关心的问题,我们以一个常见的场景为例:发送 1000 个并发 HTTP 请求(例如抓取 API 或网页)

特性 requests (同步) aiohttp (异步) httpx (异步)
并发模型 阻塞式,串行 asyncio 事件循环 anyio / asyncio 事件循环
处理 1000 请求耗时 非常慢(约 100-200 秒) 非常快(约 2-5 秒) 非常快(约 2-5 秒)
连接池复用 每次请求新建连接 自动复用 自动复用
内存占用 较低(单线程) 中等(多个协程) 中等(多个协程)
API 简洁性 最简洁直观 较复杂,需管理 ClientSession requests 几乎一致,非常简洁
底层库 urllib3 自研底层 httpcore + anyio
  • requests 相比:在并发场景下,HTTPX 异步版本的速度提升了 50-100 倍requests 根本不适合做大规模并发请求。
  • aiohttp 相比:两者在纯并发性能上非常接近,通常差距在 5% 以内,HTTPX 的代码可读性和易用性明显更好(因为它模仿了 requests 的 API),而 aiohttp 在极端优化和底层自定义方面更灵活。
  • httpx 同步版本相比:HTTPX 的异步版本比其同步版本快几个数量级,如果你的代码是 I/O 密集型的(比如大量网络请求),务必使用异步版本

实际性能影响因素

虽然 HTTPX 底层很快,但最终性能还取决于以下几个因素:

  • 并发数:HTTPX 通过 asyncio.gather()Semaphore 控制并发,默认情况下,连接池有连接数限制(如 10 个),你需要调整 limits 参数:

    import httpx
    import asyncio
    limits = httpx.Limits(max_keepalive_connections=5, max_connections=100) # 最大并发连接100
    async with httpx.AsyncClient(limits=limits) as client:
        ...

    如果并发数超过连接池上限,请求会排队等待,导致性能下降。

  • 目标服务器限制:如果你并发请求同一个网站,目标服务器可能会限流(返回 429 状态码),此时再快的客户端也没用。

  • 网络延迟:对于高延迟连接(如跨洲访问),异步能很好地并发等待,性能提升巨大,对于低延迟本地连接,提升较小。

  • 连接复用:HTTPX 自动支持 HTTP/1.1 Keep-Alive 和 HTTP/2,使用 HTTP/2 可以在单个 TCP 连接上并发发送多个请求,显著提升性能。

    # 启用 HTTP/2
    async with httpx.AsyncClient(http2=True) as client:
        ...

    注意:HTTP/2 通常能带来 10-30% 的性能提升,尤其是需要发送大量小请求时。

  • 编码与序列化:HTTPX 在读取响应时,默认会进行自动解码(如 gzip、deflate),这部分开销很小,但如果你不需要(比如下载二进制文件),可以关闭以节省 CPU:

    async with httpx.AsyncClient(default_encoding=False) as client:
        ...

代码示例:100 个并发请求性能测试

import asyncio
import httpx
import time
async def make_request(client, url):
    try:
        response = await client.get(url)
        return response.status_code
    except httpx.RequestError as e:
        return str(e)
async def main():
    url = "https://httpbin.org/delay/1"  # 模拟慢速服务器
    num_requests = 100
    limits = httpx.Limits(max_connections=50)  # 控制并发数
    async with httpx.AsyncClient(limits=limits, http2=True) as client:
        start_time = time.perf_counter()
        tasks = [make_request(client, url) for _ in range(num_requests)]
        results = await asyncio.gather(*tasks)
        end_time = time.perf_counter()
        print(f"结果:{len(results)} 个请求完成")
        print(f"耗时:{end_time - start_time:.2f} 秒")
        print(f"QPS:{num_requests / (end_time - start_time):.1f} 请求/秒")
# 运行
asyncio.run(main())

预期输出(以上述代码为例,网络环境良好):

结果:100 个请求完成
耗时:2.05 秒
QPS:48.8 请求/秒

(如果不用异步,100 个串行请求耗时约 100 秒。)

HTTPS 异步性能表现

评价维度 表现 备注
原始并发速度 🟢 极高 与业界最快的 aiohttp 持平或仅慢 5%
易用性 🟢 极高 API 与 requests 高度相似,学习成本极低
功能丰富度 🟢 原生支持 HTTP/2、SOCKS 代理、超时精细控制
稳定性 🟢 底层使用成熟的 anyiohttpcore,社区活跃,bug 修复快
极端场景性能 🟡 中等 对于需要极低延迟的连接复用,aiohttp 或自定义底层可能更优

最终建议:

  • 如果你需要高性能并发 HTTP 请求,并且希望代码简洁、现代、功能完善,HTTPX 异步版本是最好的选择之一。
  • 如果你只是做简单的少量请求(比如一个 API 调用),直接用 requests 更方便。
  • 如果你正在构建一个要求极致性能、底层高度可控的爬虫或代理服务,可以考虑 aiohttp 或基于 curio/trio 的定制方案,但普通项目完全没必要。

抱歉,评论功能暂时关闭!