为了将数据集从单个生产者传播到多个消费者,Netflix 创建了 Gutenberg 服务,它使用发布/订阅技术在微服务之间传播版本化的数据集——消费者订阅数据集,并在有新版本可用时更新数据集。Netflix 公司高级软件工程师Ammar Khaku在一篇博文中介绍了 Gutenberg 的总体设计以及一些用例。
在 Gutenberg 的数据模型中,顶层结构是主题。发布到主题将创建一个新的版本单调递增的数据模型,其中每个版本都包含元数据和一个数据指针。目前,Gutenberg 支持两种类型的数据指针:一种是数据编码在指针中,当数据集小于 1MB 时使用,另一种是指向AWS,数据存储在S3中,用于更大的数据集。
Gutenberg 的一个常见用例是从单个发布者向多个消费者传播各种大小的数据。通常,这些用例处理的配置情况是数据保存在客户端的内存中并在运行时中使用。示例包括支持支付方法的元数据和 A/B 测试配置。
另一个用例是版本化的数据存储,通常用于机器学习应用程序。团队根据历史数据构建和训练模型,运行一段时间以了解其效果,然后修改一些参数并再次运行。
Khaku 强调,Gutenberg 并不没有被设计成一个事件系统。它是为发布和消费整个数据集的不可变视图而设计的,纯粹用于数据版本控制和传播。快速发布新数据并不意味着客户端将读取所有版本。当客户端请求更新时,Gutenberg 将只提供最新版本的数据,而不提供任何以前的版本。
Gutenberg 包含一个提供 gRPC 和 REST API 的服务,以及一个使用 gRPC API 的 Java 客户端库。服务器基于一个全局复制的持久化Cassandra集群,有单独的实例组分别用于处理消费者请求和发布请求。这样就可以单独扩展,消费者请求可以比发布请求多许多,并且这两种请求类型可以互不影响。
为了处理来自消费者的大量请求,每个处理消费者请求的实例都有一个最新发布内容的内存缓存,缓存每隔几秒钟更新一次。为了防止行为不端的应用程序干扰系统,它们使用自适应并发限制器来检测和限制应用程序或服务。当使用多个区域中的 S3 桶时,服务器会设法进行优化,向客户端提供与客户端距离最近的区域中的桶。
在将数据返回给消费者之前,Gutenberg 服务首先对数据进行一致性检查。如果检查失败,服务将检查所请求主题的历史记录,并返回最新的一致数据。这是为了防止不完整的数据返回给消费者,因为 Cassandra 层有时会发生复制延迟。
Gutenberg 客户端库使用 gRPC 与 Gutenberg 服务通信,并使用Eureka进行服务发现。客户端的主要职责是管理订阅和 S3 上传/下载。当用户创建订阅并开始下载时,客户端库将开始通过每 30 秒一次的轮询来检索数据,然后将数据交给用户提供的监听器。它提供了不同类型的可配置的重试逻辑,使客户端能够根据需要处理下载问题。通常情况下,客户端总是会请求它所知道的最新版本的数据,并且只使用该版本的数据。一个例外是部署不当;为了快速缓解这种问题,可以要求客户端读取已知正确的特定版本的数据。
为了实现审计和使用情况的可见性,Gutenberg 服务拦截来自发布者和消费者的请求,并在Elasticsearch中为它们建立索引。这将创建一个视图,其中包含不同主题的使用情况和未使用的主题。
Gutenberg 的开发工作还在进行当中,正按计划增加一些新特性,包括Node.js和Python客户端支持、敏感数据加密以及改进增量发布。
原文链接:
Gutenberg – A Publish-Subscribe Service for Datasets Created by Netflix
评论