我正在使用微服务构建一个云原生应用程序。最终,我已经到了必须为我的微服务实现正确版本控制的地步。在我看过的大多数地方,现在每个人都在谈论语义版本控制(一般来说,不仅仅是针对微服务)。
微服务体系结构的原则之一是永远不要交付破坏性的变更集。另一方面,语义版本控制表示,当交付不向后兼容(读作"破坏")的变更集时,应该增加主要版本号。这些是如何兼容的?
在我看来,语义版本控制对于微服务架构来说可能是。如果所有公共api都有版本控制(例如/api/v3/getSomething),那么我真的需要完整的语义版本控制吗?我正在考虑一种方案,通过该方案,我使用一个数字来标识当前可用的API版本(v1、v2、v3等),并使用一个构建号(或者可能是日期/时间戳)来标识生成该构建的连续集成管道。请注意,在所有使用服务的人都转向使用v3之前,v3仍然支持v2 API调用,因此从某种意义上说,v3是"目标版本"。所以我的微服务foo看起来像"foo-v3-20160503142209.jar"
这里面有明显的陷阱吗?在我看来,如果我强制执行从不提供破坏性的变更集(如果它发生变化,则为新的API版本),则客户端将保证API是兼容的。客户端可以通过使用最新的内部版本号/时间戳来确定所有最新的错误修复。
在与客户的日常对话中,很难使用带有时间戳或git提交哈希的版本。因此,您可以将语义版本(v1.23中的v1)的主要部分视为API版本。您可以创建二进制foo-v1.2.3.jar,它在foo/API/v1/公开API。要引入API的新版本,您应该相应地更改二进制的版本。例如,对于API版本2,您将创建名为foo-v2.0.1.jar.的二进制文件
还努力找出版本控制的最佳方案
需要考虑的事项:
1. CI
2. Git Branching model
3. Compatibility
4. Routing
到目前为止,我使用了改进的SemVerX.Y.Z
Z用于小的修复和改进
X,Y用于标签路由
Y用于新功能
X如果更改破坏了服务之间的协议,则会修改
版本:"2.0.x",版本:"2.0.0",
文件夹结构
[Service name] -> [Release] -> [Service]
我们在微服务的基础设施中肯定会使用语义版本控制。我强烈推荐它。
我们必须做的一件事是将一些关键服务的使用锁定到他们使用的其他服务的版本。
我们使用StdLib,因此版本控制是比较容易的部分。我建议看一下他们的东西,看看他们是如何处理版本控制的。
但本质上,在处理图像上传的Article服务中,我们使用了formatImage服务的0.0.2进行了锁定。
它看起来像这样:
const lib = require('lib')({
// AWS_CREDENTIALS...
});
lib.utils.formatImage['0.0.2']({ key: 'image-key', resize: [200, 300] }, ...)
这样,我们就不必担心服务会发生变化。
尽管我确实认为,如果lib
能够从npm中的文件或类似package.json
的文件中读取这些依赖关系,那将是非常酷的。但一个人可以做梦。