在最近一篇发表在LinkedIn工程博客上的文章中,Bohan Yang描述了公司升级基于Apache ZooKeeper的服务发现平台的项目。由于拥有数千个微服务,LinkedIn面临着容量限制的问题,因此需要一种更具扩展性的架构。新系统在写入操作中使用了Apache Kafka,在读取操作中则采用了xDS协议,这种设计能够确保数据最终达成一致性,并且允许非Java语言的客户端也能正常使用该系统。为了保证系统的稳定性,开发团队实施了“双模式”策略,从而实现了无缝、无中断的系统迁移。
开发团队发现,基于Apache ZooKeeper的旧系统存在严重的扩展性问题。应用程序服务器直接进行写入操作,而客户端也直接进行读取或监控操作,这些操作会导致大规模的应用程序部署引发剧烈的写入高峰,进而导致读取请求量激增,从而造成高延迟和会话超时等问题。此外,由于ZooKeeper要求数据必须保持强一致性(即数据必须按照严格的顺序进行处理),因此读取请求的积压可能会阻塞写入操作,从而导致正常的节点也无法通过健康检查。开发团队估计,当前的系统在2025年之前就会达到其最大容量限制。
为了解决这些问题,他们设计了一种新的架构,将系统从基于强一致性的模式转变为基于数据最终一致性的模式,从而提高了系统的性能、可用性和扩展性。新系统将写入路径(通过Kafka实现)与读取路径(通过Observer服务实现)分开。Service Discovery Observer会接收Kafka发送的事件,然后更新其内存缓存,并通过xDS协议将这些更新信息推送给客户端,而该协议也与Envoy和gRPC兼容。由于采用了xDS标准,LinkedIn现在可以让使用多种语言编写的客户端正常使用这一系统了。此外,这种架构也为未来与Service Mesh(Envoy)以及集中式负载均衡系统的集成提供了可能。
这次系统迁移必须在不干扰每天数十亿次请求流程的情况下完成,同时也不能要求数千个应用程序的所有者进行任何手动设置更改。开发团队实施了双读写机制:对于读取操作,客户端会同时订阅ZooKeeper和新的Observer服务;在系统迁移的试点阶段,ZooKeeper仍然是负责路由请求的“权威数据源”,而后台线程则会不断验证Observer提供的数据是否与ZooKeeper中的数据一致,只有在确认数据一致后,才会将请求流量切换到新的系统中;对于写入操作,应用程序服务器会同时向ZooKeeper和Kafka发送写入请求。自动执行的cron任务还会持续监控ZooKeeper中的数据变化情况,以确保那些仍然在使用旧系统的客户端不会影响到新系统的正常运行。