GraphQL 服务器端流式实现
Posted
技术标签:
【中文标题】GraphQL 服务器端流式实现【英文标题】:GraphQL server side streaming implementation 【发布时间】:2020-02-08 06:05:00 【问题描述】:因此,在过去,我能够创建一个 REST 端点并使其能够流式传输大文件。我使用 Java 和 Jersey(REST 库)来做到这一点。我可以创建一个类似于下面代码的端点——客户端可以点击它,服务器会在不使用大量内存的情况下输出大文件,客户端会立即开始下载文件。
@GET
@Path("/getFile")
public Response getFile()
InputStream file = getFileStreamFromDB();
Response response = Response.ok().entity(stream);
return response;
现在我正试图弄清楚如何使用 GraphQL 应用类似的模式。用例有点不同 - 现在我从数据库而不是文件中提取大型结果集。我有一个用 Kotlin 和 KGraphQL 构建的 GraphQL 服务器。从我所做的研究来看,我似乎需要发送整个对象作为对 GraphQL 调用的响应。
我的用例是在基于 React 的仪表板上显示数据。在某些情况下,我们有大量数据,可能需要一些时间才能将响应发送到客户端,因为必须发送整个结果集。我希望将数据流式传输到仪表板中,以便用户可以立即开始查看一些数据,而不是等待 15 或 20 秒才能显示。
GraphQL 解析器可以是某种对象或字符串:
query("returnString")
resolver -> "this is a string"
但是,如果我尝试返回如下所示的 InputStream:
query("returnStream")
resolver -> (
val stream = ByteArrayInputStream("this is a string".toByteArray(Charsets.UTF_8))
stream
)
尝试启动 GraphQL 服务器时出现以下异常:
原因:com.apurebase.kgraphql.schema.SchemaException: Generic GraphQL 不支持类型,找到 () -> java.io.ByteArrayInputStream 在 com.apurebase.kgraphql.schema.structure2.SchemaCompilation.handlePossiblyWrappedType(SchemaCompilation.kt:147) 在 com.apurebase.kgraphql.schema.structure2.SchemaCompilation.handleOperation(SchemaCompilation.kt:131) 在 com.apurebase.kgraphql.schema.structure2.SchemaCompilation.handleQueries(SchemaCompilation.kt:112) 在 com.apurebase.kgraphql.schema.structure2.SchemaCompilation.perform(SchemaCompilation.kt:55) 在 com.apurebase.kgraphql.schema.dsl.SchemaBuilder.build(SchemaBuilder.kt:26) 在 com.apurebase.kgraphql.KGraphQL$Companion.schema(KGraphQL.kt:8)
我们在前端使用 apollo,所以我觉得我们可以在客户端利用流指令 - 我只是不确定如何设计 GraphQL 解析器来返回流。
有没有一种方法可以流式传输对 GraphQL 调用的响应?还是我目前必须为此使用 REST?
【问题讨论】:
这是因为ByteArrayInputStream
有一个 byteArray 字段,并且 KGraphQL github issue#55 目前不支持 java 数组。
除此之外,这只是试图返回 ByteArrayInputStream
对象,而不是实际将数据流回,因此您目前无法通过 KGraphQL 完成您想要实现的目标。
【参考方案1】:
与流响应最接近的 GraphQL 等价物可能是订阅:https://graphql.org/blog/subscriptions-in-graphql-and-relay/。将您正在做的事情作为对 DB 行“事件”的订阅来实现对我来说似乎是合理的。
KGraphQL 目前似乎没有实现这一点:https://github.com/aPureBase/KGraphQL/issues/10
不过,graphql-kotlin 项目 (https://github.com/ExpediaGroup/graphql-kotlin) 在 spring-boot 基础上实现了订阅:https://expediagroup.github.io/graphql-kotlin/docs/server/subscriptions。
如果您习惯了球衣并且更愿意坚持使用它,我们将利用 graphql-kotlin 的基础库组合一个单独的实现来在 dropwizard(球衣等)基础上实现订阅:https://github.com/trib3/leakycauldron/tree/master/graphql
【讨论】:
以上是关于GraphQL 服务器端流式实现的主要内容,如果未能解决你的问题,请参考以下文章