首页 > 解决方案 > 模式缝合的graphql微服务约定之间的通信

问题描述

我有以下我认为相当普遍的结构。我一直在寻找并找不到任何关于模式拼接服务相互调用的推荐方式的任何信息(同时仍被前端使用)。这是我的情况:

Api Gateway 模式缝合:

帖子服务使用 mongodb,用户服务使用 PostgreSQL。帖子服务的架构仅包含 user_id 而不是完整用户。当我需要一页帖子(带有相应的用户信息)时,我正在使用帖子服务中的 getPosts 解析器中的 node-fetch 调用用户服务,如下所示:

{
  getUsers(user_id__in:[1,5,9,3]){
    username
    join_date
  }
}

与 apollo-graphql 的其余部分的优雅相比,这个解决方案感觉有点“肮脏”。

是否更常见的是忽略用于解析数据的 graphql 部分并使用 apollo-graphql 的底层快速服务器提供的典型休息端点结构?如果不是,我应该直接调用其他服务还是通过 api 网关调用它们?如果我应该通过 api 网关调用它们,是否有任何内置的优雅方式可以使用某些 Apollo 功能调用 api 网关(因为服务是模式缝合的)。

标签: node.jsgraphqlapollo

解决方案


您的问题没有显示您现有的任何 API 网关代码,但我假设您正在按照 docs 中的描述拼接您的模式。每个服务的模式应该只提供适合其特定领域的字段。例如,帖子服务模式不应包含对用户的任何引用。当您将模式拼接在一起时,您可以通过提供链接不同服务的附加字段来扩展现有类型。

const extensions = `
extend type User {
  posts
}

extend type Post {
  user
}
`

const mergedSchema = mergeSchemas({
  schemas: [
    usersSchema,
    postsSchema,
    extensions,
  ],
  resolvers: {
    User: {
      posts: {
        fragment: `... on User { id }`,
        resolve(user, args, context, info) {
          return info.mergeInfo.delegateToSchema({
            schema: postsSchema,
            operation: 'query',
            fieldName: 'posts',
            args: {
              userId: user.id,
            },
            context,
            info,
          });
        },
      },
    },
    Post: {
      user: {
        fragment: `... on Post { userId }`,
        resolve(post, args, context, info) {
          return info.mergeInfo.delegateToSchema({
            schema: postsSchema,
            operation: 'query',
            fieldName: 'user',
            args: {
              id: post.userId,
            },
            context,
            info,
          });
        },
      },
    },
  },
});

在这里,我们将User类型从用户服务扩展为包含一个posts字段。我们使用delegateToSchema来指示这个额外的字段实际上应该由帖子服务的架构通过查询posts和传递用户 ID 作为userId参数来解析(实际的字段和参数名称需要与您的架构匹配)。我们类似地user为每个字段添加一个字段,Post并将解析该字段委托给用户服务模式。

请查看文档以获取更多详细信息。


推荐阅读