为什么我们决定将 API 迁移到 gRPC
Vendasta 八年前成立,最初是为小型企业提供产品的点解决方案提供商。从一开始,我们就与媒体公司和代理商合作,他们拥有大量的销售人员,并与这些企业建立了现有的关系,以销售我们的软件。据估计,仅在美国就有超过 3000 万家小型企业,因此我们从一开始就将 SaaS 解决方案的可扩展性视为我们最关心的问题之一,这也是我们从 Google App Engine 和 Datastore 入手的原因。当我们的系统从数百名扩展到数十万名最终用户时,此解决方案对我们非常有效。在此期间,我们还将我们的产品从点解决方案扩展到一个拥有多个产品的完整平台,并为合作伙伴提供了管理这些产品销售的工具。
在整个历程中,Python GAE 都很好地满足了我们的需求。我们通过 HTTP + JSON 公开了一些 API,供我们的合作伙伴自动化任务并将他们的其他系统与我们的产品和平台集成。然而,在 2016 年,我们推出了 Vendasta 市场。这标志着我们产品的重大变化,该变化严重依赖于第三方供应商使用我们的 API 在我们的平台中交付他们自己的产品。这是一个重大的变化,因为我们的公共 API 为第三方应用程序提供了上限,这让我们意识到我们真的需要制作出色的 API,而不仅仅是好的 API。
我们开始的第一个优化是使用 Go 编程语言构建端点,这些端点处理的吞吐量更高,延迟比使用 Python 低。在某些 API 上,这产生了令人难以置信的差异:我们看到第 50 个百分位的响应时间从 1200 毫秒下降到 4 毫秒,更惊人的是,第 99 个百分位的响应时间从 30,000 毫秒下降到 12 毫秒!在其他 API 上,我们看到的差异要小得多,但仍然很显著。
我们使用的第二个优化是将我们 Datastore 数据的大部分复制到 ElasticSearch 中。ElasticSearch 是一种与 Datastore 根本不同的存储技术,并且不是托管服务,因此这对我们来说是一个很大的飞跃。但是,此更改使我们能够将几乎所有夜间批处理 API 迁移到实时 API。我们曾尝试过 BigQuery,但它的查询处理时间意味着我们无法实时显示内容。我们曾尝试过 cloudSQL,但是它的数据太多,无法轻松扩展。我们曾尝试过 appengine Search API,但是它对超过 10,000 个结果集的限制。相反,我们使用 Google Container Engine 扩展了我们的 ElasticSearch 集群,凭借其强大的聚合和分面处理能力,我们的需求很容易得到满足。因此,通过这两个解决方案,我们对 API 的性能进行了有意义的更改。
我们做的最后一个优化是将我们的 API 迁移到了 gRPC。 这一改动比其他的改动影响范围更广,因为它影响了我们的客户端。和 ElasticSearch 一样,它代表了一种根本不同的模型,具有不同的性能特征,但与 ElasticSearch 不同的是,我们发现它是一个真正的超集:我们所有的使用场景都受到了它的积极影响。
我们从 gRPC 中看到的第一个好处是,我们能够从发布 API 并要求开发人员进行集成,转变为发布 SDK 并要求开发人员复制粘贴他们语言编写的示例代码。这对于希望与我们的产品集成的用户来说是一个巨大的好处,同时不需要我们用合作伙伴和供应商使用的 5 种以上的语言手动编写整个 SDK。需要注意的是,我们仍然在生成的 gRPC SDK 上编写轻量级的封装,使其对包管理器友好,并提供对生成的 protobuf 结构的封装。
我们从 gRPC 中看到的第二个好处是,我们能够摆脱 HTTP + JSON 所需的请求-响应架构。gRPC 构建在 HTTP/2 之上,允许客户端和/或服务器端流式传输。在我们的用例中,这意味着我们可以通过在服务器上准备好结果时对其进行流式传输(服务器端流式传输)来缩短首次显示的时间。我们还一直在研究提供非常灵活的创建端点的潜力,该端点可以轻松支持双向流式传输的大容量数据摄取,这意味着我们将允许客户端异步流式传输结果,而服务器将流式传输回状态,以便在不减慢上传速度以等待确认的情况下轻松进行检查点操作。我们认为我们才刚刚开始看到此功能带来的好处,因为它为客户端-服务器交互开辟了一个全新的模型,而这在 HTTP 中是不可能的。
第三个好处是从 JSON 切换到 protocol buffers,它与 gRPC 非常配合。这提高了序列化和反序列化的时间;这对我们的一些 API 非常重要,但所有 API 都很欢迎。更重要的好处来自 proto 的显式格式规范,这意味着客户端接收的是类型化的对象,而不是自由格式的 JSON。因此,我们的客户端可以在其 IDE 中获得自动完成的好处,如果他们的语言支持,则可以获得类型安全,并可以强制执行具有不同版本的客户端和服务器之间的兼容性。
gRPC 的最后一个好处是我们能够快速规范端点。用于数据和服务定义的 proto 格式极大地简化了新端点的定义,并最终允许简洁地定义端点契约。这意味着我们能够更好地在我们的开发团队之间沟通端点规范。gRPC 意味着我们公司有史以来第一次能够同时开发 API 的客户端和服务器端!这意味着我们生成带有附带 SDK 的新 API 的延迟大大降低。结合代码生成,它使我们能够真正并行开发客户端和服务器。
我们使用 gRPC 的体验是积极的,尽管它并没有消除向合作伙伴和供应商提供端点的困难,并解决我们所有的性能问题。但是,它确实改进了我们的端点性能,与这些端点的集成,甚至 SDK 的交付。