在孤立的微服务之间共享数据

时间:2016-11-04 12:24:29

标签: web-services heroku database-design web-applications microservices

我希望将微服务架构模式用于新系统,但是当服务彼此隔离时,我很难弄清楚如何在服务之间共享和合并数据。特别是,我正在考虑返回合并数据以通过HTTP填充Web应用程序UI。

对于上下文,我打算将每个服务部署到自己的孤立环境(Heroku),在那里我无法在服务之间进行内部通信(例如通过//localhost:PORT。我计划使用RabbitMQ进行服务间通信,使用Postgres进行数据库通信。

服务的分离对CREATE操作有意义:

  • UserId的认证用户提交'加入群组'前端的网络表格
  • 包含GroupJoinRequest的新UserId已添加到RabbitMQ队列
  • Groups服务会选择事件并对其进行处理,引用用户的UserId

但是,如果我想跨表/模式合并数据,则READ操作要困难得多。让我们说我想获取某个组中所有用户的详细信息。在单片设计中,我只是跨用户和组表执行SQL JOIN,但这会失去微服务的隔离优势。

我的选择似乎如下:

每个服务的数据库,每个服务的公共API

要查看Users中的所有Group,网站访问者会从“群组”服务获取与群组关联的UserID列表,然后查询Users得到他们的名字。

优点:

  • 非常明确的关注点分离
  • 每项服务都对其自己的数据负全部责任

缺点:

  • 需要多个HTTP请求
  • 很多后处理必须在客户端进行
  • 无法优化多个SQL查询

数据库每服务,服务通过HTTP共享数据,单个公共API

公共API服务器处理请求端点。 API服务器中的应用程序逻辑通过HTTP通道向每个服务发出请求,该通道只能由系统中的其他服务访问。

优点:

  • 良好的关注点分离
  • 每个服务都负责API合同,但只要API响应不会发生变化,就可以对模式和数据存储执行任何操作

缺点:

  • 非高性能
  • HTTP似乎是用于内部通信的奇怪传输机制
  • 最终将多项服务暴露给公共互联网(即使它们被理论上锁定),因此安全威胁会从更大的攻击面上增长

数据库每服务,服务通过消息代理共享数据

鉴于我已经运行了RabbitMQ,我可以使用它来排队数据请求,然后自己发送数据。例如:

  • 客户端请求组中的所有用户
  • 公共API服务使用GetUsersInGroup
  • 发送RequestID个事件
  • Groups服务选择此功能,并将UserID添加到队列
  • `用户服务选择此功能,并将用户数据添加到队列
  • API服务侦听具有RequestID的事件,等待响应,将数据合并为正确的格式,然后发送回客户端

优点:

  • 使用现有基础架构
  • 良好的脱钩
  • 服务间请求保持内部(无公共API)

缺点:

  • 多个SQL查询
  • 应用层的大量数据处理
  • 更难理解
  • 通过事件系统传递大量数据似乎很奇怪
  • 延迟?

服务共享数据库,由模式分隔,从VIEW s

读取的其他服务

服务被隔离到数据库模式中。模式只能由各自的服务写入。服务在其模式上公开可由其他服务查询的SQL VIEW层。

VIEW用作API合约;即使底层架构或服务应用程序逻辑发生更改,VIEW也会公开相同的数据,因此

优点

  • 大概更高效(单个SQL查询可以获取所有相关数据)
  • 外键管理更容易
  • 维护较少的基础架构
  • 更容易运行跨多个服务的报告

缺点:

  • 服务之间的紧密耦合
  • 打破了对彼此不了解的基本原子服务的想法
  • 添加了一个可能难以扩展的单片组件(数据库)(与可根据需要独立扩展数据库的原子服务相比)
  • 将所有服务锁定为使用相同的记录系统(Postgres可能不是所有服务的最佳数据库)

我倾向于最后一个选项,但会对其他方法的任何想法表示感谢。

1 个答案:

答案 0 :(得分:1)

为了评估优缺点,我认为您应该关注微服务架构旨在实现的目标。在我看来,微服务是一种建筑风格,旨在构建松散耦合的应用程序。它不是为构建高性能应用程序而设计的,因此当我们决定以微服务方式构建应用程序时,我们已经准备好接受性能和数据冗余的划痕。

我不认为您的服务应该共享数据库。更紧密的耦合掩盖了微服务架构的主要目标。我的建议是创建一个统一数据服务,从所有其他服务中获取数据更改事件并更新其后面的数据库。您可能希望以针对查询优化的方式(如数据仓库)设计统一数据服务后面的数据库,因为将使用所有这些服务。您可能需要考虑使用NoSQL数据库来支持整合数据服务。