From Python to Go: Why We Rewrote Our Ingest Pipeline at Telemetry Harbor

我们将 Telemetry Harbor 的摄取管道从 Python FastAPI 重写为 Go,原因是遇到了严重的性能瓶颈。迁移后,效率提升了 10 倍,数据完整性因严格类型检查而得到加强,系统也拥有了稳定、可扩展的高并发时间序列数据摄取基础。

背景:打造一个时间序列数据平台

Telemetry Harbor 源自我们在汽车行业积累的经验。几乎每个项目都要重复搭建相同的基础设施:数据库、后端、数据摄取管道、可视化界面。每次都要花费数周时间,这让我们萌生了打造一个开箱即用平台的想法。

当时的市场方案并不理想。InfluxDB 的商业化策略让许多关键特性被锁在付费墙后,版本迁移成本高且在大数据负载下表现不佳。TimescaleDB 与 ClickHouse 技术上更强大,但依旧需要用户自行构建后端与摄取管道。我们看到了缺口——需要一个极简、可靠、可直接使用的平台。

Python FastAPI:原型开发的正确选择

MVP 阶段,我们在开发速度与运行性能之间权衡。最终选择了 Python FastAPI,因为它允许我们:

早期架构非常直接:HTTP API(避免防火墙问题)、Redis + RQ 队列、TimescaleDB。测试效果良好,但很快暴露了性能隐患——RQ 的同步处理方式无法支撑高吞吐场景。

性能瓶颈:Python 无法跟上增长

随着数据量上升,性能问题逐渐浮现:

问题不仅在于 RQ 的同步限制,而是整个 Python 架构在常规负载下都难以维持稳定。这迫使我们考虑全面重写。

迁移决策:为什么选择 Go?

我们评估了 Rust 和 Go:

最终选择 Go,以兼顾性能与开发速度。

重写摄取管道

我们使用 Go Fiber 框架实现新服务,确保与 Python 版本 API 兼容,并通过版本控制平滑过渡(v1 为 Python,v2 为 Go)。

性能提升显著:

应用层性能瓶颈彻底消除。

工程挑战:数据库约束处理

我们必须防止同一设备、货物、时间戳的重复数据。批量写入时,如果一条记录冲突,PostgreSQL 会拒绝整个批次。

解决方案是两阶段插入:

  1. 将数据写入临时表
  2. 由 PostgreSQL 从临时表中选择并插入合法记录

既保证性能,又维持数据完整性。

新瓶颈:数据库性能

随着应用层变得高效,PostgreSQL 成为主要性能瓶颈。这是好事,数据库扩展手段更多(分片、只读副本、水平分区),可支持更高吞吐。

意外发现:Pydantic 的类型强制转换

在 Go 版本中,400 错误率升高。调查发现,Python/Pydantic 会隐式转换类型:

Go 严格拒绝此类数据,暴露了 Python 版本未检测的数据质量问题。我们决定保留 Go 的严格校验,防止潜在数据污染。

现状与未来

目前两版 API 并行运行,新客户使用 Go v2。下一步将进行数据库分片以支持更大规模。

经验教训

  1. 快速原型,但要知道何时重写
  2. 性能不仅是速度,更是可预测性
  3. 类型安全能避免长期数据问题
  4. 严格校验比灵活容错更可靠

结论

Python 帮助我们快速验证市场并上线,而 Go 为我们提供了可扩展、稳定、可靠的生产基础。对于面临类似抉择的团队:当现有技术无法支撑下一阶段增长时,不要害怕重写。

Start searching

Enter keywords to search articles

↑↓
ESC
⌘K Shortcut