微服务之间的关系应该如何架构

Posted

技术标签:

【中文标题】微服务之间的关系应该如何架构【英文标题】:How should be the schema on relations between microservices 【发布时间】:2020-08-11 13:48:42 【问题描述】:

我正在使用 NestJS + Prisma + Apollo Federation。

在微服务 A 上定义用户,在微服务 B 上定义帖子。 关系是 1 - N,一个用户可以有 N 个帖子。

在 Prisma 中,Post 的数据模型是用一个字符串为用户定义的,因为 userId 是一个 uuid。

type Post 
  id: Int! @id
  createdAt: DateTime! @createdAt
  updatedAt: DateTime! @updatedAt
  user: String!

在生成的模式(https://graphql-code-generator.com)中,Post 有一个 User 类型的属性,而这种 User 类型扩展了 id 和一个帖子数组:

type Post @key(fields: "id") 
  id: Int!
  createdAt: DateTime!
  updatedAt: DateTime!
  user: User!


extend type User @key(fields: "id") 
  id: ID! @external
  posts: [Post]

在 apollo federation 中,一切都按预期工作,除非在尝试链接两个微服务之间进行查询。

在操场上,如果您尝试使用其用户查询帖子而不设置子字段,它会破坏架构并说您必须设置用户的子字段,如果您设置子字段,graphql 会回复一条消息,您不能使用子字段因为它的类型是字符串。

我可以使这项工作正常工作的唯一方法是在 Prisma 中设置字符串类型的 userId 字段并在模式中设置另一个字段,称为用户类型的用户。但是所有示例都没有显示一个与 db 一起使用的字段和一个与 schema 一起使用的字段。

我的问题是这是推荐的还是我遗漏了什么。

【问题讨论】:

【参考方案1】:

为了从Post 获取User,您必须在您的帖子和用户服务中创建解析器。

邮政服务

const resolvers = 
  Post://before you do this you have to extend User schema which you already did.
      // you are basically asking the 'User' service, which field should be used to query user.
    user: ref => ( __typename: 'User', id: ref.userId )
  
  Query:
    // query resolvers
  ,
  Mutation:
    // mutation resolvers
  

用户服务

const resolvers = 
  User://the code below allows other services to extend User in their own schemas
    __resolveReference: (ref,  userDataLoader ) => userDataLoader.load(ref.id),
  
  Query:
    // query resolvers
  ,
  Mutation:
    // mutation resolvers
  

现在像[Post] 这样的链接数组必须完全在后期服务中完成

邮政服务

const resolvers = 
  Post://before you do this you have to extend User schema which you already did.
      // you are basically telling the user service, which field should be used to query user.
    user: ref => ( __typename: 'User', id: ref.user )
  ,
  User:
    posts:(ref, args, postDataLoader) => getOrders(ref.postIds) //or ref.userId(foreign key)
  ,
  Query:
    // query resolvers
  ,
  Mutation:
    // mutation resolvers
  

【讨论】:

只是为了确保您不需要在数据库模式中创建关系,对吧?如果我理解正确,在 DB 级别不需要任何关系,因为 Apollo 联邦将在解析器中解析它们,对吗? 一般来说,每个服务都有自己的数据库和表集。单个数据库中的数据应该具有数据库级别的关系。但是对于数据存储在另一个服务(单独的数据库)中的情况,关系是在服务器中建立的。而且在这种情况下也不可能在数据库级别建立关系,因为这两组数据位于两个不同的数据库中 是的,完美的 Sihoon。我就是这么想的。谢谢

以上是关于微服务之间的关系应该如何架构的主要内容,如果未能解决你的问题,请参考以下文章

DevOps架构下如何进行微服务性能测试

微服务架构下的服务治理:如何在 SpringCloud 框架中实现服务的注册与发现

Docker 微服务架构 - 不同容器之间的通信

了解微服务

云原生时代,微服务如何演进?

SpringCloud01:回顾微服务和微服务架构