RSS

我们为什么决定将 API 迁移到 gRPC

Vendasta 在八年前起步时,是一家为小型企业提供单一解决方案的供应商。从一开始,我们就与拥有庞大销售团队并与这些企业建立了现有关系的媒体公司和代理机构合作,销售我们的软件。据估计,仅在美国就有超过 3000 万家小型企业,因此我们 SaaS 解决方案的可扩展性从一开始就是我们的首要关注点之一,这也是我们最初选择 Google App Engine 和 Datastore 的原因。随着我们的系统从数百名用户扩展到数十万名最终用户,这个解决方案对我们来说非常有效。在此期间,我们还将产品从单一解决方案扩展为包含多个产品的完整平台,并为合作伙伴提供了管理这些产品销售的工具。

在整个发展过程中,Python GAE 很好地满足了我们的需求。我们通过 HTTP + JSON 方式开放了大量 API,供我们的合作伙伴自动化任务并将其其他系统与我们的产品和平台集成。然而,在 2016 年,我们推出了 Vendasta Marketplace。这标志着我们的产品发生了重大变化,它严重依赖于第三方供应商使用我们的 API 在我们的平台上提供他们自己的产品。这是一个重大的变化,因为我们的公共 API 对第三方应用程序施加了上限,并使我们意识到我们确实需要打造卓越而非仅仅良好的 API。

我们开始进行的第一个优化是使用 Go 编程语言来构建端点,以实现比 Python 更高的吞吐量和更低的延迟。在某些 API 上,这带来了令人难以置信的差异:我们看到 50% 响应时间从 1200 毫秒降至 4 毫秒,更惊人的是 99% 响应时间从 30,000 毫秒降至 12 毫秒!在其他 API 上,我们看到了小得多但仍然显著的差异。

我们使用的第二个优化是将大部分 Datastore 数据复制到 ElasticSearch 中。ElasticSearch 是一种与 Datastore 截然不同的存储技术,并且不是托管服务,因此这对我们来说是一个巨大的飞跃。但这一改变使我们能够将几乎所有夜间批处理 API 迁移到实时 API。我们曾尝试过 BigQuery,但其查询处理时间意味着我们无法实时显示数据。我们曾尝试过 cloudSQL,但数据量太大,难以轻松扩展。我们曾尝试过 App Engine Search API,但它在结果集超过 10,000 条时存在限制。我们转而使用 Google Container Engine 扩展了我们的 ElasticSearch 集群,凭借其强大的聚合和分面处理能力,我们的需求得到了轻松满足。因此,有了这两个解决方案,我们对 API 的性能做出了有意义的改变。

我们进行的最后一次优化是将我们的 API 迁移到 gRPC。这一改变比其他优化更为广泛,因为它影响了我们的客户端。与 ElasticSearch 类似,它代表了一种具有不同性能特征的根本不同的模型,但与 ElasticSearch 不同的是,我们发现它是一个真正的超集:我们所有的使用场景都受到了它的积极影响。

我们从 gRPC 中看到的第一个好处是,我们能够从发布 API 并要求开发人员进行集成,转变为发布 SDK 并要求开发人员复制粘贴他们语言编写的示例代码。这对于希望集成我们产品的人来说是一个巨大的好处,同时也不需要我们为合作伙伴和供应商使用的 5 种以上语言手动编写完整的 SDK。需要注意的是,我们仍然在生成的 gRPC SDK 之上编写轻量级封装,以使其易于包管理器管理,并为生成的 protobuf 结构提供封装。

我们从 gRPC 中看到的第二个好处是,我们能够摆脱 HTTP + JSON 所必需的请求-响应(call-and-response)架构。gRPC 构建在 HTTP/2 之上,这允许客户端和/或服务器端流式传输。在我们的用例中,这意味着我们可以通过在服务器上结果准备好时进行流式传输(服务器端流式传输)来缩短首次显示时间。我们还在研究提供非常灵活的创建端点的潜力,这些端点可以轻松支持双向流式传输的批量数据摄入,这意味着我们将允许客户端异步流式传输结果,同时服务器将流回状态,从而实现简单的检查点操作,同时不减慢上传速度以等待确认。我们认为,我们才刚刚开始看到此功能带来的好处,因为它为客户端-服务器交互开辟了一个全新的模式,而这在 HTTP 下是不可能实现的。

第三个好处是从 JSON 切换到 Protocol Buffers,这与 gRPC 配合得非常好。这提高了序列化和反序列化时间;这对我们的一些 API 来说非常重要,但对所有 API 都很有益。更重要的好处来自于 proto 的显式格式规范,这意味着客户端接收的是类型化对象,而不是自由形式的 JSON。因此,我们的客户端可以享受到 IDE 中的自动完成、如果其语言支持的类型安全以及客户端和服务器之间不同版本强制兼容性所带来的好处。

gRPC 的最后一个好处是我们能够快速定义端点。用于数据和服务定义的 proto 格式极大地简化了新端点的定义,并最终允许简洁地定义端点契约。这意味着我们能够更好地在开发团队之间沟通端点规范。gRPC 意味着,在我们的公司,我们首次能够同时开发 API 的客户端和服务器端!这意味着我们生成新 API 和配套 SDK 的延迟时间已大幅下降。结合代码生成,它使我们能够真正并行地开发客户端和服务器。

我们使用 gRPC 的体验是积极的,尽管它并未完全消除向合作伙伴和供应商提供端点的难度,也未能解决我们所有的性能问题。然而,它确实改进了我们的端点性能、与这些端点的集成,甚至还改进了 SDK 的交付。