为了确保功能可以一次一个地顺利部署,它们需要保持向后兼容性。这意味着您需要能够处于服务 A 已部署但服务 B 已部署的中间阶段。微服务中的每次更改都需要尽可能小以最大程度地降低风险,并且应该在部署时引入一个更改一次。
为什么我们不同时部署它们呢?因为同时发布两个微服务是危险的。首先,部署不是即时的,因此有时过时的服务会发送或接收系统未准备好处理的调用。这将产生可能影响您的客户的错误。
但是有可能发生其中一个微服务不正确并且需要回滚的情况。然后,系统处于不一致的状态。依赖的微服务也需要回滚。这本身就是有问题的,但是当在调试这个问题的过程中,两个微服务都被卡住并且在问题得到解决之前无法更新时,它会使事情变得更糟。
在健康的微服务环境中,会经常发生部署。因为另一个服务需要工作而不得不停止微服务的管道是一个不好的位置,它只会增加压力和紧迫感。
Remember that we talked about the speed of deployment and change. Deploying small increments
often is the best way to ensure that each deployment will be of high quality. The constant flow of incremental work is very important.
Interrupting this flow due to an error is bad, but the effect multiplies quickly if the inability to deploy affects the pace of multiple microservices.
同时部署的多个服务也可能会造成死锁,这两个服务都需要工作来解决问题。这会使开发和解决问题的时间变得复杂。
需要进行分析以确定哪个微服务依赖于另一个,而不是同时部署。大多数时候,这是显而易见的。在我们的示例中,前端依赖于 Thoughts Backend,因此涉及它们的任何更改都需要从 Thoughts Backend 开始,然后移至 Frontend。
实际上,Users Backend 是两者的依赖关系,所以假设有一个更改会影响它们三个,您需要先更改 Users Backend,然后是 Thoughts Backend,最后是 Frontend。
请记住,有时,部署可能需要多次跨服务移动。例如,假设我们对身份验证标头的签名机制进行了更改。那么这个过程应该如下:
- Implement the new authentication system in the Users Backend, but keep producing tokens with the old system through a config change. The old authentication process is still used in the cluster so far.
- Change the Thoughts Backend to allow working with both the old and the new system of authenticating. Note that it is not activated yet.
- Change the Frontend to work with both authentication systems. Still, at this point, the new system is not yet used.
- Change configuration in the Users Backend to produce new authentication tokens. Now is when the new system starts to be used. While the deployment is underway, some old system tokens may be generated.
- The Users Backend and Frontend will work with any token in the system, either new or old. Old tokens will disappear over time, as they expire. New tokens are the only ones being created.
- As an optional stage, the old authentication system can be deleted from the systems. The three systems can delete them without any dependency as the system is not used at this point.
在过程的任何步骤,服务都不会中断。每个单独的更改都是安全的。这个过程正在慢慢地使整个系统进化,但是如果出现问题,每个单独的步骤都是可逆的,并且服务不会中断。
系统倾向于通过添加新功能来发展,很少有清理阶段。通常,系统会在很长一段时间内使用已弃用的功能,即使该功能在任何地方都没有使用。
We will talk a bit more about clean-up in
Chapter 12,
Collaborating and Communicating across Teams.
配置更改也可能需要此过程。在示例中,更改签署身份验证标头所需的私钥将需要以下步骤:
- Make the Thoughts Backend and Frontend able to handle more than one public key. This is a prerequisite and a new feature.
- Change the handled keys in the Thoughts Backend to have both the old and the new public keys. So far, no headers signed with the new key are flowing in the system.
- Change the handled keys in the Frontend to have both the old and the new. Still, no headers signed with the new key are flowing in the system.
- Change the configuration of the Users Backend to use the new private key. From now on, there are headers signed with the new private key in the system. Other microservices are able to handle them.
- The system still accepts headers signed with the old key. Wait for a safe period to ensure all old headers are expired.
- Remove the configuration for the old key in the Users Backend.
可以每隔几个月重复步骤 2 到 6 以使用新密钥。
此过程称为 密钥轮换, 它被认为是一种良好的安全实践,因为它会在密钥有效时缩短寿命,从而减少窗口系统很容易受到泄露的密钥的影响。为简单起见,我们没有在示例系统中实现它,但作为推荐练习保留这样做。尝试更改示例代码以实现此密钥轮换示例!
完整的系统功能可能涉及多个服务和团队。为了帮助协调系统的依赖关系,我们需要知道服务的某个依赖关系何时部署并准备就绪。我们将在 Chapter 12 中讨论团队间的沟通,Collaborating和跨团队通信,但我们可以通过使服务 API 明确描述部署的服务版本来以编程方式提供帮助,正如我们将在处理服务依赖项中讨论的那样部分。
如果刚刚部署的新版本出现问题,可以通过回滚快速恢复部署。