19

在我们公司,我们正在从一个巨大的单体应用程序过渡到一个微服务架构。这个决定的主要技术驱动因素是需要能够独立扩展服务和开发的可扩展性——我们有十个 Scrum 团队在不同的项目(或“微服务”)中工作。

过渡过程很顺利,我们已经开始受益于这种新技术和组织结构的优势。现在,另一方面,我们正在努力解决一个主要的痛点:如何管理这些微服务之间的依赖关系的“状态”

让我们举个例子:其中一个微服务处理用户和注册。该服务(我们称之为 X)负责维护身份信息,因此是用户“id”的主要提供者。其余的微服务对这个有很强的依赖。例如,有一些服务负责用户配置文件信息 (A)、用户权限 (B)、用户组 (C) 等,它们依赖于这些用户 ID,因此需要在这些服务之间维护一些数据同步(即服务 A 不应该有未在服务 X 中注册的用户 ID 的信息)。我们目前通过使用 RabbitMQ 通知状态更改(例如新注册)来保持这种同步。

可以想象,有许多X:许多“主要”服务以及它们之间的许多更复杂的依赖关系。

管理不同的开发/测试环境时出现的主要问题。每个团队(因此,每个服务)都需要经过几个环境才能使一些代码生效:持续集成、团队集成、验收测试和实时环境。

显然,我们需要在所有这些环境中工作的所有服务来检查系统是否作为一个整体工作。现在,这意味着为了测试依赖服务(A,B,C,...),我们不仅要依赖服务 X,还要依赖它的状态。因此,我们需要以某种方式维护系统完整性并存储全局和连贯的状态

我们目前的方法是从实时环境中获取所有数据库的快照,进行一些转换以缩小和保护数据隐私,并在特定环境中进行测试之前将其传播到所有环境。这显然是组织和计算资源方面的巨大开销:我们有十个持续集成环境、十个集成环境和一个验收测试环境,所有这些环境都需要使用来自实时和最新版本代码的共享数据“刷新”频繁地。

我们正在努力寻找更好的方法来缓解这种痛苦。目前我们正在评估两种选择:

  1. 为所有这些服务使用类似 docker 的容器
  2. 每个服务有两个版本(一个用于开发该服务,另一个作为沙箱供其他团队在开发和集成测试中使用)

这些解决方案都不能减轻服务之间共享数据的痛苦。我们想知道其他一些公司/开发人员是如何解决这个问题的,因为我们认为这在微服务架构中一定很常见。

你们怎么样?你也有这个问题吗?有什么推荐吗?

很抱歉解释太长,非常感谢!

4

3 回答 3

9

这次我从不同的角度阅读了你的问题,所以这里是一个“不同的意见”。我知道这可能为时已晚,但希望它有助于进一步发展。

看起来shared state是错误解耦的结果。在“正确”的微服务架构中,所有微服务都必须在功能上而不是逻辑上隔离。我的意思是这三者user profile information (A), user permissions (B), user groups (C)在功能上看起来都一样,而且在功能上或多或少是连贯的。它们似乎是user microservice具有连贯存储的单个。我在这里看不到任何使它们脱钩的原因(或者至少您没有告诉它们)。

所以真正的问题与微服务隔离有关。理想情况下,每个微服务都可以作为完整的独立产品存在并提供明确定义的业务价值。在详细说明系统架构时,我们将其分解为微小的逻辑单元(在您的情况下为 A、B、C 等,甚至更小),然后定义功能上一致的子组。我不能告诉你如何做到这一点的确切规则,也许是一些例子。单元之间复杂的通信/依赖关系,在其普遍存在的语言中有许多常用术语,因此看起来这些单元属于同一个功能组,因此属于微服务。

因此,从您的示例来看,由于只有一个存储,因此您只有像以前那样管理其一致性的方法。

顺便说一句,我想知道您解决问题的实际方法是什么?另外,如果您喜欢我的想法,请随意接受。

于 2015-07-13T10:14:00.637 回答
1

让我尝试重新表述问题:

演员:

  • X:UserIds(账户状态)
    • 提供服务以获取 ID(基于凭据)和帐户状态
  • A:用户资料
    • 使用 X 检查用户帐户的状态。存储名称以及帐户链接
    • 提供基于 ID 获取/编辑名称的服务
  • B:用户博客
    • 以同样的方式使用 X。当用户写一篇文章时,将博客文章与帐户链接一起存储
    • 使用A根据用户名搜索博文
    • 提供基于 ID 的服务获取/编辑博客条目列表
    • 提供基于名称搜索博客文章的服务(依赖A)
  • C:移动应用
    • 将 X、A、B 的特征包装到移动应用程序中
    • 提供上述所有服务,依赖于与所有其他人的明确定义的通信合同(遵循@neleus 声明)

要求:

  1. X、A、B、C 团队的工作需要解耦
  2. X、A、B、C 的集成环境需要使用最新功能进行更新(以便执行集成测试)
  3. X、A、B、C 的集成环境需要有“足够的”数据集(为了执行负载测试,并找到边缘情况)

遵循@eugene 的想法:对每个团队提供的每项服务进行模拟将允许 1) 和 2)

  • 成本是团队的更多发展
  • 还维护模拟以及主要功能
  • 障碍是你有一个单一的系统(你还没有一套干净的定义良好/隔离的服务)

建议的解决方案:

与一组主数据共享环境来解决 3) 怎么样?每个“交付的服务”(即在生产中运行)都是可用的。每个团队都可以选择他们将从这里使用的服务以及他们将从自己的环境中使用的服务

我可以看到的一个直接缺点是数据的共享状态和一致性。

让我们考虑针对主数据运行的自动化测试,例如:

  • B 更改名称(由 A 拥有)以便在其博客服务上工作
    • 可能会破坏 A 或 C
  • A 更改帐户的状态以处理某些权限方案
    • 可能会破坏 X、B
  • C 在同一个帐户上更改所有内容
    • 打破所有其他

主数据集将很快变得不一致并失去其对上述要求 3) 的价值。

因此,我们可以在共享主数据上添加一个“常规”层:任何人都可以读取完整的数据集,但只能修改他们创建的对象?

于 2015-03-06T10:41:01.223 回答
0

从我的角度来看,只有使用服务的对象才应该具有状态。让我们考虑您的示例:服务 X 负责用户 ID,服务 A 负责配置文件信息等。让我们假设用户 Y 具有一些安全令牌(例如可以通过使用其用户名和密码创建 - 应该是唯一)进入系统。然后,包含用户信息的客户端将安全令牌发送到服务 X。服务 X 包含有关链接到此类令牌的用户 ID 的信息。如果是新用户,服务 X 会创建新 ID 并存储它的令牌。然后服务 X 将 ID 返回给用户对象。用户对象通过提供用户 ID 向服务 A 询问用户配置文件。服务 A 获取 ID 并询问服务 X 是否存在该 ID。服务 X 发送肯定答案,然后服务 A 可以通过用户 ID 搜索配置文件信息或要求用户提供此类信息以创建它。相同的逻辑应该适用于 B 和 C 服务。他们必须互相交谈,但他们不需要知道用户状态。

关于环境的几句话。我建议使用puppets。这是自动化服务部署过程的方法。我们正在使用 puppet 在不同的环境中部署服务。puppet 脚本是可触及的,并允许灵活配置。

于 2015-03-03T09:30:57.770 回答