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