有一个微服务(.Net core,但这不是那么重要)。新功能在其中实现,它们在某个地方发生了变化DTO,并且这个实现需要制作一个新版本(v2),同时保持旧功能(v1)。
已提出以下选项:
v1从当前分支创建一个分支master,提交它并将其布置为单独的实例。在更正影响两个分支的逻辑时,请进行cherry-pick适当的提交。- 复制逻辑
v1并v2在一个解决方案中,将其分布在不同的命名空间中,实现两个控制器 - forv1和v2.
第一种方法涉及基础设施成本。第二个在代码形式上非常丑陋。
问题:什么重要best practice?也许还有一些我们没有考虑过的第三种(第四、第五)方法?
前言
如您所知,没有“单一”和/或“理想”的方法来解决这个问题,在每个特定案例的上下文中只有最方便和最不方便的方法。我可以提供一个开发团队,在我所处的环境中,通过反复试验得到的。
一般优惠 (
client-side和server-side)我建议使用接近您提出的第一个选项的选项,即 根据质量的组合,将您的微服务版本拆分
v1为v22 个独立的模块(客户端的 2 个客户端库和服务器端的 2 个文凭单元):随着后续版本服务的进一步出现(因为您有第二个版本的服务,那么很可能第三个版本将在稍后出现),遵循类似的策略。
微服务的介绍
feature和bug fix其他改进:在开发版本化微服务时,至少应该区分 -versions(
major格式minor)${major-version}.${minor-version}:minor发生在同一版本的服务中major需要分配新版本的服务应根据以下规则进行改进:
minor的相同版本的上下文中,通过提高版本进行不破坏向后兼容性的修订majormajor-version,即创建服务的新版本Client-side(为客户端提供)提供客户端库以使用您的微服务:
通常,服务开发人员还提供了一个客户端库来处理他们的微服务,它提供了一个方便的 API 并封装了集成交互的细节:
http通过微服务的后端间接发送 -requestload balancer,即 进入处理针对相应服务版本的请求的 Web 应用程序http其与来自 API 的用户友好类覆盖,将它们作为返回值提供如果您提供一个客户端库来处理您的微服务,那么在目标解决方案中,最方便的是也可以按服务版本拆分它,但需要注意以下几点:
major客户端库的 -version 必须与major与之关联的微服务的 -version 匹配(major-version 是您在问题上下文中简单地称为 version)major提供自己的版本APInamespace在C#package在Java...解释:
通过给
API每个版本一个单独的“空间”,您可以让用户API在同一模块中同时使用多个版本的代码,这在版本之间的过渡期间尤其需要。例如,对于您的服务的消费者而言,当其模块(已经在使用旧版本)的整个转换到服务的新版本时,可能是一项耗时的任务,或者在特殊情况下,不需要完全过渡。
Server-side(为服务器端提供)在服务器端,根据整体质量为每个版本的服务分配单独的文凭单元(独立工件):
n'th 个服务版本的能力Endpoint's /Conteoller's 的 Web 应用程序仅在相应版本的服务的上下文中处理请求)随着后续版本服务的进一步出现(因为您有第二个版本的服务,那么很可能第三个版本将在稍后出现),遵循类似的策略。
解释:
对于每个版本的微服务,您分配一个单独的模块/工件,它将作为 Web 应用程序文凭的单独单元交付。这些文凭单元中的每一个都将在微服务版本上下文中的独特上下文中上升:
some/web/app/context/v1some/web/app/context/v2...some/web/app/context/vn由于在 Web 应用程序上下文级别进行版本控制,这种解决方案可能看起来不太优雅(不是每个人都会喜欢在 url 中明确指定版本的想法),但值得给出一些理由赞成这个解决方案,使它看起来不那么令人厌恶:
L7 load balancing(OSI / ISOL7网络模型)到运行这些微服务的 Web 应用程序的相应实例,例如,通过:Nginxupstream为每个版本的服务启动一个单独的location为每个版本的服务启动一个单独的location's 将请求代理到相应版本的服务upstreamupstream为服务的相应版本之一生成load balancing一个 Web 应用程序(它只处理对某个版本的服务的请求),即使对应于不同版本的微服务的多个 Web 应用程序部署在一个应用程序服务器的上下文中。Load balancing例如,由以下算法之一生成:Round RobinIP-HashLeast connected(在这种情况下,nginx端将需要维护一个最新的活动列表connection,即 http 连接)...数据库使用:
如果需要使用持久数据存储来正确运行微服务,则可以使用以下方法之一来对数据模式进行版本控制:
您可以在链接中阅读有关对数据库模式进行版本控制的第二种方法,因此我将告诉您第一种方法,这是本答案上下文中最合乎逻辑的解决方案。
作为隔离数据的一种方法,您可以查看最常见的两种:
各种数据库
+高水平的数据隔离这种情况下,隔离级别将取决于托管不同版本服务数据的数据库的服务器,如果它们不同,那么即使一台服务器也不会影响其数据的服务不存储。
-一次用于维护多个数据库实例(甚至可能是不同的数据库)的额外的、巨大的服务器资源(CPU、RAM 和 ROM)成本通过使用的数据库提供的隔离机制
-在容错方面缺乏隔离(一个数据库的下降会影响所有版本的服务的运行)一般来说,隔离的级别将取决于数据库内部对分区的抵抗力(
partition tolerance来自CAP定理)+几乎完全没有服务器资源的额外成本例如,如果您使用 Oracle DBMS 存储不同版本服务的数据,您可以实现以下方法之一:
使用不同的数据模式
DataSource一个用于处理数据库的包装器,它将请求上下文切换到所需的数据模式 (ALTER SESSION SET CURRENT_SCHEMA),以避免在对数据库的查询中显式指定数据模式使用分区机制(分片)
VERSION),从而隐式指示Oracle DBMS进行搜索仅在某个分区文件中,迫使它忽略其余部分,因为它们保证缺少所请求版本的服务的数据在大多数情况下,从成本需求比来看,数据隔离的第二种选择是最合适的。
值得注意的是,如果你有一些特殊的业务逻辑假设通过更高版本的服务你必须可以访问更低版本的数据,那么没有人禁止写一个周期性启动的(特别是一次性的)从包含较低版本数据的存储到包含较高版本数据的存储的数据转换器。
例如,在 DBMS 的情况下,
Oracle转换器可以写为PL/SQL存储过程附言
我的整个帖子在某种程度上是在术语的上下文中呈现的
java enterprise,但我希望以上内容能够以某种方式充分应用于您的.Net应用程序的体系结构。类似的情况引发了许多问题: - 两个版本的开发是否会并行,如果可以,持续多长时间?- 版本有什么
v2不同v1?如果第一个版本的开发处于错误修复级别,那么第一个选项。
如果并行开发时间长,版本差异很大,那么也是第一种选择。
如果并行开发持续了很长时间,版本差异不大,那么可以在旧控制器中添加新方法,名称中带有前缀,并在外部决定请求路由级别,并
/v1/<action>在引擎盖controller/action和/v2/<action>引擎盖下controller/v2Action。