在akka-http中,当响应不是200时,响应实体是否需要在接收器中使用?

时间:2016-08-19 21:41:56

标签: scala akka akka-stream akka-http

在这个akka-http documentation page上,底部有一个警告:

  

确保使用响应实体   dataBytes:Source[ByteString,Unit]例如将其连接到   接收器(例如response.entity.dataBytes.runWith(Sink.ignore) if   你不关心响应实体),否则Akka HTTP   (以及底层的Streams基础设施)将了解缺乏   实体消费作为背压信号并停止读取   底层的TCP连接!

     

这是Akka HTTP的一个功能,允许消费实体(和   以流媒体方式将它们拉过网络)   当客户端准备好消耗字节时需求 - 可能有点   起初很惊讶。

为什么在响应的状态代码不是StatusCodes.OK的情况下不需要这样做?或者它实际上是否需要并且该页面(也在下面)上显示的代码示例错过了?

  def receive = {
    case HttpResponse(StatusCodes.OK, headers, entity, _) =>
      log.info("Got response, body: " + entity.dataBytes.runFold(ByteString(""))(_ ++ _))
    case HttpResponse(code, _, _, _) =>
      //why not here?
      log.info("Request failed, response code: " + code)
  }

1 个答案:

答案 0 :(得分:2)

应始终使用响应实体,但在实践中,错误响应通常为HttpEntity.Strict类型,并且未能消耗那些不会导致任何背压问题。

对于感兴趣的人,从Akka 2.4.9开始,此行为来自SlotProcessor.running,其中HttpEntity使用HttpEntity.captureTermination包裹HttpEntity.Strict。该包裹用于表示响应已被消耗,从而提供正确的背压信号。对于captureTermination,因为实体主体已在内存中,Future.success(())方法将返回Source,而其他类型将包裹Future并返回Source在基础HttpEntity完成时完成。

关于返回的HttpEntity.Strict类型,就API而言,没有任何保证,某些响应将为HttpEntity.Strict,这就是为什么建议始终使用响应。 HttpResponseParser正在进行解析响应的工作。据我所知,当读取响应时,如果正文已经读入内存(基于缓冲区大小)并且没有传输编码,则可以返回HttpEntity.Default,因为我们已经完成了所有工作。否则,将返回HttpEntity.ChunkedHttpEntity

在最后一次捕获时,如果您使用complete作为服务器响应的一部分(例如在withRequestTimeoutResponse指令中),那么服务器可能会超时并且不会费力消耗该实体。在这种情况下,您可以使用dojo.attr指令来使用响应。