如何在微服务中处理数据库架构更新

时间:2019-01-04 08:59:23

标签: database architecture microservices

我们将从这种模式开始

CREATE TABLE [dbo].[Label]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Prefix] VARCHAR(50) NOT NULL UNIQUE,
    [ArtistName] VARCHAR(MAX) NOT NULL
)

我们还有一个管理“标签”的微服务。 http://labels.example.com/v1/all将以以下格式返回所有标签:

{ Id = xxx, Prefix = xxx, ArtistName = xxx }

我们如何处理不影响此微服务使用者的架构更改?

我们必须进行一些重构,然后艺术家移动到自己的桌子上。

CREATE TABLE [dbo].[Label]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Prefix] VARCHAR(50) NOT NULL UNIQUE,
    [ArtistId] UNIQUEIDENTIFIER NOT NULL,

    CONSTRAINT FK_Label_Artist
        FOREIGN KEY (ArtistId) REFERENCES Artist(Id)
)

CREATE TABLE [dbo].[Artist]
(
    [Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, 
    [Name] VARCHAR(MAX) NOT NULL,
    [Country] VARCHAR(MAX) NOT NULL
)

我们的微服务将需要返回以下对象

{ Id = xxx, Prefix = xxx, Artist = { Id = xxx, Name = xxx, Country = xxx } }

我们将必须创建一个v2 api调用,以返回此新结构。我们还必须将数据迁移到新结构。这意味着v1也需要更改以支持新的架构,但它仍将返回相同的对象。

版本化微服务时,事情就是这样吗?要记住的事情?有其他方法吗?

2 个答案:

答案 0 :(得分:1)

听起来您在正确的轨道上。发明了微服务架构样式,以允许组织建立逻辑上分离的具有清晰定义接口的开发团队。这些接口是服务API或其他向消费者公开的接口。

数据库模式应该是服务内部的,因此应作为常规开发过程的一部分随着时间的推移进行开发。仅在对服务使用者产生影响(通过更改服务界面)的情况下,才必须确保有正式的版本控制过程。

正式过程应包括适用于外部依赖项的所有方面。您可以以facebook为例,因为它们会发布其公共API的新版本而过一会又过时的旧API。您应该有类似的过程,即通过时间表提前通知消费者,然后同时部署新旧服务版本,以便消费者有时间采用并最终淘汰旧服务。当您同时运行这两种服务时,您应该监视两者的流量,并在流量未随时间切换时向消费者发送提醒。

因此,简而言之-像对待外部依赖项一样对待内部依赖项。

一些其他想法:

  • 扩展比修改容易:有时您无需扩展API返回的数据结构,而不会破坏现有的使用者。在您的示例中,这可能意味着返回如下结构:

    function formatDates(dates) {
        return dates.map((date) => {
            const d = new Date(date.replace(/(st)|(nd)|(rd)|(th)/ig, ""));
            const yyyy = d.getFullYear();
            const mm = "" + (d.getMonth() + 1);
            const dd = "" + d.getDate();
    
            return  `${yyyy}-${mm.length === 1? "0" + mm: mm}-${dd.length === 1? "0" + dd: dd}` ;
        }) 
    }
    
    var dates = ['2nd Oct 2014', '20th Oct 2014', '20th May 2019']
    console.log(formatDates(dates)); // [ '2014-10-02', '2014-10-20', '2019-05-20' ]
    

    在这里您将为保持兼容性而在数据上进行冗余。

  • 您应该经常进行更改:通常最好在单个版本升级中累积很多更改,而不是经常进行很少更改的升级。

  • 您可以使用版本模式来指示重大更改:例如,次要版本更改1.1与版本1.0兼容,而主要版本更改2.0与1.1版本不兼容。

  • 客户端适配器:有时,客户端库附带API,以使访问更加轻松且不受传输格式等的影响。在这种情况下,客户端库也需要正确版本控制,并应支持所有活动版本。

  • 工具:浏览诸如GraphQL之类的标准,这些标准可帮助完成许多与API相关的任务。

答案 1 :(得分:0)

有几种方法可以做到这一点,我发现最“正确”的方法是使用media types,以便客户端可以指定期望返回的版本。这将使实现的rest服务可以向后移植数据结构,以便仍可以使用旧版本。前提是这不是一项重大更改,而是需要谁

相关问题