aioinflux默认使用同步requests导致await卡住或报runtimeerror;必须显式设mode='async'并安装aiohttp依赖,配合batch_size批量写入、带时区datetime时间处理及tcpconnector连接池调优才能实现真正异步高效写入。

为什么直接用 aioinflux 的 write 会卡住或报错
常见现象是程序跑着突然停在 await client.write(...),或者抛出 RuntimeError: await wasn't used with a future。根本原因是 aioinflux 的默认客户端(InfluxDBClient)不是真正异步的——它底层封装的是同步的 requests,即使你用了 async/await,也会在事件循环里阻塞线程。
必须显式启用异步后端:初始化时传入 mode='async',并确保使用 aiohttp(而非 requests)作为传输层:
from aioinflux import InfluxDBClient <p>client = InfluxDBClient( host='localhost', port=8086, db='mydb', mode='async' # ⚠️ 缺少这行就不是真异步 ) </p>
-
mode='sync'(默认):走requests,不能在async函数里直接await -
mode='async':依赖aiohttp,要求 Python ≥ 3.7,且需手动pip install aioinflux[aiohttp] - 若已安装但报
ModuleNotFoundError: No module named 'aiohttp',说明没装可选依赖
批量写入时如何避免 ConnectionResetError 或超时
高频小数据点(比如每秒百条)直接逐条 await client.write(...),容易触发连接复用失败或服务端限流,表现为 ConnectionResetError: [Errno 104] Connection reset by peer 或 TimeoutError。
正确做法是攒批、压缩、控制并发:
- 用
client.write的batch_size参数(如batch_size=500),它会在内存中缓冲,达到数量或超时(flush_interval,默认 0.5 秒)后一次性发 HTTP 请求 - 写入前把多条数据构造成一个
list[dict],字段统一为measurement、tags、fields、time(时间戳推荐用datetime对象,aioinflux会自动转 RFC3339) - 不要在循环里反复创建
client实例;复用单个 client,它是线程安全且支持并发await write()
示例:
points = [
{
'measurement': 'cpu',
'tags': {'host': 'server01'},
'fields': {'usage': 23.4},
'time': datetime.utcnow()
},
# ... 更多点
]
await client.write(points, batch_size=1000, protocol='line')
如何处理时区和时间精度问题
aioinflux 默认把 datetime 对象转成纳秒级 Unix 时间戳并带上 UTC 时区。如果你传的是本地时间(比如 datetime.now()),又没设时区,InfluxDB 会按 UTC 解析,导致数据“偏移 8 小时”。
关键点:
- 始终用带时区的
datetime:推荐datetime.now(timezone.utc)或datetime.utcnow().replace(tzinfo=timezone.utc) - 避免用字符串时间(如
"2024-05-20T10:00:00Z"),虽然能解析,但精度可能被截断;datetime对象可保留微秒级精度 - 如果需要毫秒级精度(InfluxDB 默认纳秒),可在写入前用
dt.replace(microsecond=dt.microsecond // 1000 * 1000)截断,或在查询时用GROUP BY time(1m)聚合
连接池耗尽或 Too many open files 怎么办
高并发写入时,aiohttp 默认连接池(Connector)可能不够用,表现是请求变慢、连接超时,甚至系统报 OSError: [Errno 24] Too many open files。
需在初始化 client 时定制连接器:
- 通过
session_params控制连接数:session_params={'connector': aiohttp.TCPConnector(limit=100, limit_per_host=20)} - 禁用 DNS 缓存(可选):
use_dns_cache=False,避免长连接下 DNS 变更不生效 - 设置合理的超时:
timeout=aiohttp.ClientTimeout(total=10),防止个别请求拖垮整个队列
完整初始化示例:
import aiohttp
from aioinflux import InfluxDBClient
<p>connector = aiohttp.TCPConnector(
limit=50,
limit_per_host=10,
keepalive_timeout=30
)
client = InfluxDBClient(
host='localhost',
port=8086,
db='mydb',
mode='async',
session_params={
'connector': connector,
'timeout': aiohttp.ClientTimeout(total=5)
}
)
</p>
真正异步写入的关键不在语法有没有 async,而在于是否切断了同步 I/O 的链路、是否适配了服务端吞吐节奏、以及时间与连接这些隐性资源是否被精确控制。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











