迈向有状态系统的零停机升级

这是一篇关于软件系统升级的技术文章,主要内容总结如下:

  • 动机(Motivation):大多数部署的程序都需要在某个时候进行升级,编程语言却往往无法提供帮助。Erlang/OTP 是个例外,其 release 库可用于执行升级和降级,实现零停机时间和服务不间断。本文旨在探讨如何借鉴 Erlang 的想法实现软件系统的升级。良好的升级支持应具备零停机时间、类型安全的状态迁移、向后和向前兼容性、原子性和降级等特性。
  • 术语(Terminology)

    • 软件系统(Software systems):包括仅客户端、客户端 - 服务器(无状态和有状态组件)、分布式有状态系统等不同类型。本文重点关注有状态系统的升级,因其升级路径较复杂,但希望所提技术能简化其他系统的升级。
    • 程序及其升级(Programs and their upgrades):以状态机来表示程序及其升级,状态机是从输入和状态到输出和新状态的简单函数。通过改变状态机的输入、输出、状态等类型,可以实现程序的升级。还可以通过构建状态机的管道来实现并行处理,以处理多个客户端。
  • 实现(Implementation)

    • 状态机(State machines):使用带有类型参数的T数据类型来表示typed state machines,通过不同的构造函数定义各种操作,如身份、组合、读取、写入等。
    • 示例(Example):以计数器为例重新实现了状态机,通过模式匹配和函数组合来定义计数器的状态机函数。
    • 语义(Semantics):使用Statemonad来解释typed state machines,通过一系列函数定义了状态机的运行语义,如runTeval等。
    • 管道(Pipelines):用类似于typed state machines的类型来表示管道,管道可以看作是连接状态机的传送带,每个状态机可以有自己的状态。
    • 部署(Deployment):管道可以部署在多个线程上,通过队列连接状态机。部署状态机时,创建新队列,fork新线程进行处理,并根据输入消息进行状态机的运行和状态迁移。
    • 升级(Upgrades):升级以序列化格式发送,接收端需要通过类型检查来重建类型信息。定义了UpgradeData_UpgradeData数据类型来表示升级,通过typeCheckUpgrade函数进行类型检查。还定义了typeCheck函数来检查未类型化的状态机并将其转换为类型化的状态机。
    • 源和汇(Sources and sinks):引入了SourceSink的概念,用于提供输入和消费输出队列,方便与各种数据源和汇进行连接。
    • 远程升级(Remote upgrades):通过 TCP 服务器和客户端实现了远程升级,发送类型擦除的新状态机版本进行升级,并展示了不同类型的升级示例,如添加重置功能和状态迁移。
  • 讨论与未来工作(Discussion and future work):回顾了升级的特性,讨论了降级、向后和向前兼容性等问题,提出可以使用接口描述语言进行输入和输出迁移,还提到了一些在工作中想到但尚未解决的问题,希望能进一步完善软件系统的升级机制,使其更符合实际需求。

文中还引用了一些相关的理论和实践,如 Yuri Gurevich 的抽象状态机理论、Joe Armstrong 的 Erlang/OTP 示例、Leslie Lamport 的 TLA+以及 Jean-Raymond Abrial 的 B 方法等,以支持文中的观点和技术实现。

阅读 13
0 条评论