【问题标题】:Should multi-threading always be used in GrpahQL's DataFetcher?GrpahQL 的 DataFetcher 中是否应该始终使用多线程?
【发布时间】:2021-10-03 09:47:09
【问题描述】:

我正在使用 GraphQL java 实现。

虽然 GraphQL 的优势之一是并行获取不同的字段,但我发现如果我不在 DataFetchers 中使用像 CompletableFuture 这样的多线程方法,则只有一个线程在使用。

所以我的问题是,我是否应该始终在 DataFetcher 中使用多线程,如下面的official doc 所示,即使它只是从一个源(例如数据库)而不是多个源获取?

似乎这是推荐的方法,至少不会造成伤害。

但我想听听更有经验的开发者的意见。

提前致谢!

【问题讨论】:

    标签: java multithreading graphql graphql-java


    【解决方案1】:

    在graphql-java实现中,默认情况下,所有的resolver都是按顺序调用的。

    考虑下面的架构

    type Query {
     allPost: [Post!]
    }
    
    type Post {
      id: ID!
      tittle: String!
      postDetail: PostDetail!
      comments: [Comments!]
    }
    
    type PostDetail {
      id: ID!
      # This can be converted into enum
      postMediaType: String! 
      postUrl: String!
    }
    
    type Comment{
     id:ID!
     name: String!
     description: String!
    }
    

    这是对上面给出的模式的查询

    {
      allPost{
        id
        tittle
        postDetail {
         id
         postMediaType
         postUrl
        }
        comments{
         id
         name
         description
        }
      }
    }
    

    当服务器首先执行此查询时,将调用 Post 解析器,如果 Post 解析器未返回 cmets 或 postDetail 数据,则 graphQL 将尝试搜索相应的解析器,如果找不到,服务器将在启动期间失败.

    现在,graphQL 服务器将首先调用 PostDetail 解析器并等待其完成,然后调用 Comments Resolver 来获取该帖子的所有 cmets 列表。

    我们可以看到,即使 PostDetail 解析器和 Comments 解析器不相互依赖,解析器也是按顺序调用的。 这是我们可以使用 CompletableFuture 使 PostDetail 解析器和 Comments 解析器异步的地方。

    在这种情况下,首先将调用 Post 解析器,然后 graphql 将调用 PostDetail 解析器,该解析器将返回 CompletableFuture,然后它将调用 Comments 解析器,该解析器也将返回 CompletableFuture,稍后当这两个未来都完成时,它会发回响应给客户。

    因此它不取决于您拥有的数据源的数量 GraphQL 不关心不同类型的数据源,它只关心类型/字段的 Datafecters 的接线。

    如果它们之间没有依赖关系,您可以并行运行解析器。

    【讨论】:

    • 感谢您的回答。简而言之,我们应该始终并行运行解析器,对吗?你提到前提是there is no dependency between them,但是依赖是由GraphQL处理的,我们开发者不用担心。换句话说,我们可以在每个 DataFetcher 中使用CompletableFuture
    • GrphQL 首先将查询转换为 AST(将其视为一棵树),GraphQL 始终以广度优先顺序运行查询,因此在上述答案中,graphQL 首先会加载 Post,然后运行PostDetail 和 Comment 如果它们是异步的,并且 GraphQL 将始终在子解析器中传递父对象,因此在我们的 PostDetail 和评论解析器的例子中,我们将可以访问 Post
    • 对不起,我不能接受这个答案,因为它不包含对我问题的直接答案,尽管它非常清楚地解释了机制。还是谢谢你们!
    • 直接回答。是的,对于 Query 类型,您可以完全异步。前提是您没有潜入解析器中的 Datafetching 环境以获取一些数据,因为它可能直到现在还没有加载。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-03
    • 2016-02-16
    • 2020-03-06
    • 2012-06-17
    • 1970-01-01
    • 2015-10-03
    • 1970-01-01
    相关资源
    最近更新 更多