0

0

优化 aiohttp 大请求性能:解决 JSON 序列化与 DNS 解析瓶颈

DDD

DDD

发布时间:2025-07-28 19:24:12

|

514人浏览过

|

来源于php中文网

原创

优化 aiohttp 大请求性能:解决 JSON 序列化与 DNS 解析瓶颈

本文旨在解决使用 aiohttp 发送大量大型 HTTP POST 请求时遇到的性能瓶颈,特别是 JSON 序列化阻塞事件循环和 DNS 解析延迟问题。我们将探讨如何通过预先序列化数据、利用 asyncio.to_thread 避免阻塞,以及通过安装 aiohttp[speedups] 或直接使用 IP 地址来加速 DNS 解析,从而提升并发请求的效率和响应速度。

aiohttp 大请求的性能挑战

在使用 aiohttp 发送大量(例如 50 个)大型(例如每个 5mb)http post 请求时,开发者可能会遇到显著的性能问题。核心挑战在于 aiohttp 内部处理 json 参数时,json 序列化过程(如 json.dumps)是同步且耗时的。对于大型数据负载,这可能导致事件循环被阻塞数十毫秒甚至更长时间。在 asyncio.gather 等并发场景下,这意味着所有请求的序列化操作会串行执行,导致请求并非“可用即发送”,而是等待所有序列化完成后才批量发送,从而显著增加整体延迟。

此外,DNS 解析也是潜在的性能瓶颈,尤其是在高并发或延迟敏感的应用中,每次新的连接都可能涉及 DNS 查询。

解决方案一:优化 JSON 数据序列化

aiohttp 的 ClientSession.post 方法提供了一个 json 参数,方便地处理 JSON 数据的序列化和 Content-Type 头设置。然而,对于大型数据,这种便利性是以阻塞事件循环为代价的。为了避免这种情况,我们应该手动进行 JSON 序列化,并确保这个阻塞操作在独立的线程中执行,不影响主事件循环。

1.1 手动预序列化数据

不再使用 json 参数,而是将 Python 对象预先序列化为字节串,并通过 data 参数传递。同时,手动设置 Content-Type 头。

import json
import asyncio
import aiohttp

async def prepare_data_in_thread(obj) -> bytes:
    """在单独的线程中同步执行 JSON 序列化,避免阻塞事件循环。"""
    # json.dumps 是同步操作,对于大对象会阻塞,因此使用 asyncio.to_thread
    return await asyncio.to_thread(lambda: json.dumps(obj).encode('utf-8'))

async def send_large_post_request(session: aiohttp.ClientSession, url: str, payload: dict):
    """
    发送一个大型 POST 请求,数据预先序列化。
    """
    # 1. 在单独的线程中序列化数据
    serialized_data = await prepare_data_in_thread(payload)

    # 2. 使用 data 参数发送预序列化后的字节数据
    #    并手动设置 Content-Type 头
    headers = {"Content-Type": "application/json"}
    async with session.post(url, data=serialized_data, headers=headers) as response:
        response.raise_for_status() # 检查 HTTP 状态码
        return await response.text()

async def main():
    target_url = "http://example.com/api/upload" # 替换为你的 API 地址
    # 构造一个大型的模拟数据负载
    large_payload = {"key": "value" * 1000000, "data": [i for i in range(100000)]}

    async with aiohttp.ClientSession() as session:
        tasks = []
        for i in range(50): # 发送 50 个大请求
            print(f"准备发送请求 {i+1}...")
            tasks.append(send_large_post_request(session, target_url, large_payload))

        print("所有请求已准备,等待完成...")
        responses = await asyncio.gather(*tasks)
        print("所有请求完成。")
        # print(responses) # 根据需要处理响应

if __name__ == "__main__":
    asyncio.run(main())

1.2 注意事项

  • asyncio.to_thread 的重要性:json.dumps 是一个同步的、CPU 密集型操作。如果直接在主协程中调用它,即使数据准备好了,事件循环依然会被阻塞。asyncio.to_thread 确保了 json.dumps 在一个单独的线程池中执行,从而释放主事件循环,使其能够继续处理其他 I/O 任务(例如,一旦一个请求的序列化完成,它就可以立即被发送出去,而不是等待所有请求都序列化完毕)。
  • 数据不变性:在将数据传递给 asyncio.to_thread 进行序列化时,请确保原始 Python 对象在序列化过程中不会被修改。最好使用不可变的数据结构或在传递前创建数据的副本。
  • 编码:确保将字符串编码为字节,通常使用 UTF-8。json.dumps(...).encode('utf-8') 是标准做法。

解决方案二:优化 DNS 解析速度

DNS 解析是网络请求生命周期中的一个关键步骤。如果 DNS 解析速度慢,即使后端服务器响应迅速,整体延迟也会增加。

2.1 安装 aiohttp[speedups]

aiohttp 提供了可选的“加速包”,其中包含了 aiodns 库,它是一个异步 DNS 解析器。安装 aiohttp[speedups] 可以显著提升 DNS 解析性能。

pip install aiohttp[speedups]

安装后,aiohttp 会自动检测并使用 aiodns 进行 DNS 解析,无需额外的代码修改。

玄鲸Timeline
玄鲸Timeline

一个AI驱动的历史时间线生成平台

下载

2.2 直接使用 IP 地址

如果你的应用场景允许,并且你知道目标服务的 IP 地址,可以直接在 URL 中使用 IP 地址而不是域名。这将完全跳过 DNS 解析步骤,从而消除 DNS 带来的延迟。

# 替换为实际的 IP 地址和端口
target_url_with_ip = "http://192.168.1.100:8080/api/upload"

然而,这种方法通常不适用于生产环境,因为 IP 地址可能会变化,并且不利于负载均衡和服务发现。

2.3 复用 ClientSession

这是一个非常重要的性能优化点,无论是否涉及大请求或 DNS 优化。每次创建 aiohttp.ClientSession 都会建立新的连接池和 DNS 缓存。重复创建会丢弃之前的 DNS 缓存和 TCP 连接,导致性能下降。始终复用同一个 ClientSession 实例,尤其是在发送多个请求时。

# 错误示例:每次请求都创建新的 session
# async def bad_example():
#     for _ in range(50):
#         async with aiohttp.ClientSession() as session:
#             await session.post(...)

# 正确示例:复用 session
async def good_example():
    async with aiohttp.ClientSession() as session: # session 只创建一次
        tasks = []
        for _ in range(50):
            tasks.append(send_large_post_request(session, "...", {}))
        await asyncio.gather(*tasks)

总结

优化 aiohttp 处理大量大型请求的性能,关键在于识别并解决阻塞事件循环的操作。通过以下策略,可以显著提升应用的响应性和吞吐量:

  1. 预序列化 JSON 数据:避免使用 json 参数,手动将 Python 对象序列化为字节串,并通过 data 参数传递。
  2. 利用 asyncio.to_thread:将耗时的同步 JSON 序列化操作放入单独的线程中执行,防止阻塞主事件循环。
  3. 优化 DNS 解析:安装 aiohttp[speedups] 以利用 aiodns 进行异步 DNS 解析,或在特定场景下直接使用 IP 地址。
  4. 复用 ClientSession:这是最基本的性能优化,确保连接池和 DNS 缓存得到有效利用。

通过实施这些优化措施,您的 aiohttp 应用程序将能够更高效、更快速地处理高并发的大型 HTTP 请求。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

419

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

535

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

311

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

299

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

212

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1502

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

624

2023.11.24

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

0

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号