GrpahQL 的 DataFetcher 中是不是应该始终使用多线程?

Posted

技术标签:

【中文标题】GrpahQL 的 DataFetcher 中是不是应该始终使用多线程?【英文标题】: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 所示,即使它只是从一个源(例如数据库)而不是多个源获取?

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

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

提前致谢!

【问题讨论】:

【参考方案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 环境以获取一些数据,因为它可能直到现在还没有加载。

以上是关于GrpahQL 的 DataFetcher 中是不是应该始终使用多线程?的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL Java:使用@Batched DataFetcher

带有 Spring 的 GraphQL-java - 解析器 vd datafetcher

检测对象属性是不是在 PHP 中是私有的

无法分配给属性:“self”在 UIViewControllerRepresentable 中是不可变的

原始类型变量在 PL/SQL 代码中是不可变的吗?

如何确定给定时区中的给定时间是不是在postgresql中是DST?