了解 Blue 如何通过 Rust 和可扩展架构以及战略技术选择将 CSV 导入和导出扩展 10 倍,适用于 B2B SaaS。


在 Blue,我们一直在不断推动项目管理软件的可能性。多年来,我们已经发布了数百个功能

我们最新的工程壮举?

对我们的CSV 导入导出系统进行了全面的改造,显著提高了性能和可扩展性。

这篇文章带您深入了解我们如何应对这一挑战、所采用的技术以及取得的令人印象深刻的成果。

这里最有趣的是,我们不得不走出我们典型的技术栈,以实现我们想要的结果。这是一个需要深思熟虑的决定,因为长期的后果可能在技术债务和长期维护开销方面是严重的。

针对企业需求的扩展

我们的旅程始于来自活动行业的一位企业客户的请求。该客户将 Blue 作为管理大量活动、场地和演讲者的中央枢纽,并与他们的网站无缝集成。

对他们来说,Blue 不仅仅是一个工具——它是他们整个运营的唯一真实来源。

虽然我们总是为客户将我们用于如此关键的需求而感到自豪,但我们也肩负着确保系统快速、可靠的重大责任。

随着该客户扩展其运营,他们面临着一个重大障碍:导入和导出包含 100,000 到 200,000+ 记录的大型 CSV 文件。

这超出了我们当时系统的能力。事实上,我们之前的导入/导出系统已经在处理超过 10,000 到 20,000 记录的导入和导出时感到吃力!所以 200,000+ 记录根本不可能。

用户经历了令人沮丧的长等待时间,在某些情况下,导入或导出甚至会完全无法完成。这显著影响了他们的运营,因为他们依赖每日的导入和导出来管理运营的某些方面。

多租户是一种架构,其中单个软件实例为多个客户(租户)提供服务。虽然高效,但它需要仔细的资源管理,以确保一个租户的操作不会对其他租户产生负面影响。

而且这个限制不仅影响了这个特定客户。

由于我们的多租户架构——多个客户共享相同的基础设施——单个资源密集型的导入或导出可能会减缓其他用户的操作,这在实践中经常发生。

和往常一样,我们进行了自建与购买的分析,以了解我们是否应该花时间升级自己的系统或从其他地方购买系统。我们考虑了各种可能性。

唯一突出的供应商是一个名为 Flatfile 的 SaaS 提供商。他们的系统和能力看起来正是我们所需的。

但是,在审查他们的定价后,我们决定这将成为一个对我们规模的应用来说极其昂贵的解决方案——每个文件 $2 的费用很快就会累积起来!——因此最好扩展我们内置的 CSV 导入/导出引擎。

为了应对这一挑战,我们做出了一个大胆的决定:将 Rust 引入我们的主要 Javascript 技术栈中。这种以性能和安全性著称的系统编程语言,是我们性能关键的 CSV 解析和数据映射需求的完美工具。

以下是我们解决方案的实施方式。

引入后台服务

我们解决方案的基础是引入后台服务来处理资源密集型任务。这种方法使我们能够将重处理从主服务器卸载,从而显著提高整体系统性能。
我们的后台服务架构是以可扩展性为目标设计的。与我们基础设施的所有组件一样,这些服务根据需求自动扩展。

这意味着在高峰期,当多个大型导入或导出同时处理时,系统会自动分配更多资源来处理增加的负载。相反,在较安静的时期,它会缩减以优化资源使用。

这种可扩展的后台服务架构不仅使 Blue 在 CSV 导入和导出方面受益。随着时间的推移,我们将大量功能迁移到后台服务中,以减轻主服务器的负担:

  • 公式计算:将复杂的数学运算卸载,以确保快速更新派生字段而不影响主服务器性能。
  • 仪表板/图表:在后台处理大型数据集,以生成最新的可视化效果,而不会减慢用户界面。
  • 搜索索引:在后台持续更新搜索索引,确保快速准确的搜索结果而不影响系统性能。
  • 复制项目:在后台处理大型复杂项目的复制,允许用户在复制创建时继续工作。
  • 项目管理自动化:在后台执行用户定义的自动化工作流,确保及时操作而不阻塞其他操作。
  • 重复记录:在后台生成定期任务或事件,保持时间表的准确性而不增加主应用的负担。
  • 时间持续时间自定义字段:持续计算和更新 Blue 中两个事件之间的时间差,提供实时持续时间数据而不影响系统响应能力。

新的 Rust 模块用于数据解析

我们 CSV 处理解决方案的核心是一个自定义的 Rust 模块。虽然这标志着我们第一次走出核心的 Javascript 技术栈,但使用 Rust 的决定是由于其在并发操作和文件处理任务中的卓越性能。

Rust 的强项与 CSV 解析和数据映射的需求完全一致。它的零成本抽象允许高层次编程而不牺牲性能,同时其所有权模型确保内存安全而无需垃圾回收。这些特性使 Rust 特别擅长高效安全地处理大型数据集。

对于 CSV 解析,我们利用了 Rust 的 csv crate,它提供高性能的 CSV 数据读取和写入。我们将其与自定义数据映射逻辑相结合,以确保与 Blue 的数据结构无缝集成。

学习 Rust 的曲线陡峭但可管理。我们的团队花了大约两周的时间进行密集学习。

改进的效果令人印象深刻:

我们的新系统可以在大约 30 秒内处理与旧系统在 15 分钟内处理的相同数量的记录。

Web 服务器与数据库交互

对于我们 Rust 实现的 Web 服务器组件,我们选择了 Rocket 作为我们的框架。Rocket 以其性能和开发者友好的特性脱颖而出。其静态类型和编译时检查与 Rust 的安全原则很好地对齐,帮助我们在开发过程中及早发现潜在问题。
在数据库方面,我们选择了 SQLx。这个 Rust 的异步 SQL 库提供了几个优势,使其非常适合我们的需求:

  • 类型安全的 SQL:SQLx 允许我们编写原始 SQL,并进行编译时检查的查询,确保类型安全而不牺牲性能。
  • 异步支持:这与 Rocket 和我们对高效、非阻塞数据库操作的需求很好地对齐。
  • 数据库无关性:虽然我们主要使用 AWS Aurora,它与 MySQL 兼容,但 SQLx 对多种数据库的支持为我们未来的灵活性提供了保障,以防我们决定更改。

批处理优化

我们优化批处理配置的旅程是一次严格测试和仔细分析的过程。我们进行了广泛的基准测试,测试了不同的并发事务和块大小组合,测量的不仅是原始速度,还有资源利用率和系统稳定性。

该过程涉及创建不同大小和复杂度的测试数据集,模拟现实世界的使用模式。然后,我们将这些数据集通过我们的系统运行,调整每次运行的并发事务数量和块大小。

在分析结果后,我们发现处理 5 个并发事务和 500 记录的块大小提供了速度和资源利用率的最佳平衡。该配置使我们能够保持高吞吐量,而不至于压垮我们的数据库或消耗过多内存。

有趣的是,我们发现将并发性增加到 5 个事务并没有带来显著的性能提升,有时甚至导致数据库争用增加。同样,较大的块大小提高了原始速度,但以更高的内存使用和较长的响应时间为代价,尤其是在小到中等规模的导入/导出时。

通过电子邮件链接导出 CSV

我们解决方案的最后一部分解决了将大型导出文件交付给用户的挑战。我们没有提供从我们的 Web 应用程序直接下载的方式,这可能导致超时问题和增加服务器负载,而是实施了一种电子邮件下载链接的系统。

当用户发起大型导出时,我们的系统在后台处理请求。一旦完成,我们不会保持连接开放或将文件存储在我们的 Web 服务器上,而是将文件上传到一个安全的临时存储位置。然后,我们生成一个唯一的安全下载链接并将其发送给用户的电子邮件。

这些下载链接有效期为 2 小时,平衡了用户便利性和信息安全性。这个时间框架为用户提供了充足的机会来获取他们的数据,同时确保敏感信息不会无限期地保持可访问状态。

这些下载链接的安全性是我们设计中的重中之重。每个链接都是:

  • 唯一且随机生成,几乎不可能被猜测
  • 仅在 2 小时内有效
  • 在传输中加密,确保数据在下载时的安全性

这种方法提供了几个好处:

  • 减少了我们 Web 服务器的负担,因为它们不需要直接处理大型文件下载
  • 改善了用户体验,特别是对于那些可能在直接下载时面临浏览器超时问题的慢速互联网连接用户
  • 为可能超过典型 Web 超时限制的非常大型导出提供了更可靠的解决方案

用户对这一功能的反馈非常积极,许多人赞赏它在管理大型数据导出时提供的灵活性。

导出过滤后的数据

另一个显而易见的改进是允许用户仅导出在其项目视图中已过滤的数据。这意味着如果存在活动标签“优先级”,那么只有具有此标签的记录才会出现在 CSV 导出中。这意味着在 Excel 中操纵数据以过滤不重要的内容所需的时间更少,同时也帮助我们减少需要处理的行数。

展望未来

虽然我们没有立即扩展使用 Rust 的计划,但这个项目向我们展示了这种技术在性能关键操作中的潜力。这是我们现在在未来优化需求工具包中拥有的一个令人兴奋的选项。这次 CSV 导入和导出的改造与 Blue 对可扩展性的承诺完美契合。

我们致力于提供一个与客户共同成长的平台,处理他们不断扩展的数据需求,而不妥协于性能。

将 Rust 引入我们的技术栈的决定并不是轻率做出的。它提出了一个许多工程团队面临的重要问题:何时适合走出核心技术栈,何时应该坚持使用熟悉的工具?

没有一种适合所有人的答案,但在 Blue,我们已经制定了一个框架来做出这些关键决策:

  • 问题优先方法: 我们总是首先明确我们要解决的问题。在这种情况下,我们需要显著提高大型数据集的 CSV 导入和导出的性能。
  • 耗尽现有解决方案: 在寻找核心栈之外的解决方案之前,我们会彻底探索现有技术可以实现的目标。这通常涉及分析、优化和在熟悉的约束内重新思考我们的方法。
  • 量化潜在收益: 如果我们考虑一种新技术,我们需要能够清晰地表述,并且理想情况下量化其好处。对于我们的 CSV 项目,我们预计处理速度将有数量级的改善。
  • 评估成本: 引入新技术不仅仅是关于当前项目。我们考虑长期成本:
    • 团队的学习曲线
    • 持续的维护和支持
    • 部署和操作中的潜在复杂性
    • 对招聘和团队组成的影响
  • 控制和集成: 如果我们确实引入新技术,我们的目标是将其限制在系统的特定、明确的部分。我们还确保有一个明确的计划,说明它将如何与我们现有的技术栈集成。
  • 未来保障: 我们考虑这一技术选择是否打开了未来的机会,或者是否可能将我们限制在一个角落。

频繁采用新技术的主要风险之一是最终形成我们所称的*“技术动物园”*——一个碎片化的生态系统,其中应用程序的不同部分使用不同的语言或框架编写,需要广泛的专业技能来维护。

结论

这个项目体现了 Blue 的工程理念:我们不怕走出舒适区,采用新技术,只要这意味着为我们的用户提供显著更好的体验。

通过重新构想我们的 CSV 导入和导出过程,我们不仅解决了一个企业客户的紧迫需求,还改善了所有处理大型数据集的用户的体验。

随着我们继续推动项目管理软件的可能性,我们期待着迎接更多这样的挑战。

敬请关注更多关于推动 Blue 的工程的深入探讨!

AI助手

响应是通过人工智能生成的,可能包含错误。

我能帮您什么?

随时问我关于 Blue 或本文档的任何问题。

输入发送 • Shift+Enter 换行 • ⌘I 打开