【问题标题】:Spring WebClient: Parse + Stream very large JSONSpring WebClient:解析+流非常大的JSON
【发布时间】:2019-01-11 14:19:03
【问题描述】:

这个问题类似于Spring reactive streaming data from regular WebClient request,不同之处在于我没有立即从我的 WebClient 获取 JSON 数组,而是像这样:

这个 JSON 对象可能非常大(~100MB),因此需要处理并流式传输到客户端,而不是解析。这是我似乎能够使语义正确的唯一方法:

{
   "result-set":{
      "docs":[
         {
            "id":"auhcsasb1005_100000"
         },
         {
            "id":"auhcsasb1005_1000000"
         },
         {
            "id":"auhcsasb1005_1000001"
         },
         {
            "id":"auhcsasb1005_1000002"
         },
         ...
         ...
         {
            "EOF":true
         }
      ]
   }
}
WebClient.create()
  .get()
  .retrieve()
  .bodyToMono(DontKnowWhatClass.class)
  .flatMapMany(resultSet -> Flux.fromIterable(resultSet.getDocs()))

但这意味着我要反序列化 100MB 或更多的内存,然后从中创建通量。我想知道的是:我错过了一些重要的东西吗?我可以以某种方式从这样的对象创建一个 Flux 吗?遗憾的是,我现在有办法影响结果集对象的呈现方式。

【问题讨论】:

  • 那么,100 MB 有什么问题?
  • @k-nicholas 有 20 个并发请求,它突然变成了 2GB。它无法扩展。

标签: spring-webflux


【解决方案1】:

您可以接受 ServerWebExchange 到您的控制器,该控制器有一个方法将采用 Publisher exchange.response.writeWith()

如果您有办法以块的形式解析有效负载,您只需创建一个发射部分的 Flux。

例如,如果您根本不关心有效负载,只想按原样发送:

    @GetMapping("/api/foo/{myId}")
    fun foo(exchange: ServerWebExchange, @PathVariable myId: Long): Mono<Void> {
        val content: Flux<DataBuffer> = webClient
            .get()
            .uri("/api/up-stream/bar/$myId")
            .exchange()
            .flatMapMany { it.bodyToFlux<DataBuffer>() }

        return exchange.response.writeWith(content)
    }

确保检查内容协商设置以避免出现意外缓冲。

【讨论】:

  • 我遇到的最大问题是,我确实关心内容,并且我想解析数组条目,而不是包含 Json 对象;我的假设是错误的吗,普通的 json 解析器会解析到对象的末尾,然后才能进行进一步的处理?我发现 writeWith 听起来不错。
  • 那么你需要找到一种方法来生成你想要的值的Flux。 JSON 库通常会根据需要解析整个内容,以了解它是否格式正确。你可能不得不降到更低的水平。在我发布的代码中,您将在DataBuffer 中获得它的“块”,但您可能需要做一些记录才能从“网络”层跳转到“应用程序”层,类似于 XML 时代的 SAX 处理.似乎 Jackson 提供了这样的 API baeldung.com/jackson-streaming-api
  • 啊,现在我记得了,最后我求助于类似的东西,这是一个 apache solr 流响应解析器,并让每个文档事件或其他东西的输出......但使用普通 json 是我发现这是一个更好的主意,因为 SolrClient 比我当时需要的要多得多...感谢 json 流式提示!
  • 这并没有解决提出的问题。原始发布者希望生成解析后的 JSON 元素的通量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
相关资源
最近更新 更多