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



在这个akkahttp文档页面的底部有一个警告:

确保使用响应实体dataBytes:Source[ByteString,Unit],例如将其连接到接收器(例如response.entity.dataBytes.runWith(Sink.ignore),如果您不关心响应实体(,否则AkkaHTTP(以及基础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)
  }

应始终使用响应实体,但在实践中,错误响应通常为HttpEntity.Strict类型,如果不使用这些响应,则不会导致任何背压问题。

对于感兴趣的人来说,从Akka 2.4.9开始,这种行为来自SlotProcessor.running,其中它使用HttpEntity.captureTermination包装HttpEntity。这种包装用于发出响应已被消耗的信号,从而提供正确的背压信号。对于HttpEntity.Strict,由于实体主体已经在内存中,因此captureTermination方法将返回Future.success(()),而其他类型将封装Source并返回在底层Source完成时完成的Future

关于返回的HttpEntity类型,就API而言,不能保证某些响应将是HttpEntity.Strict,这就是为什么建议始终使用响应的原因。HttpResponseParser正在分析响应。正如我在读取响应时所理解的,如果主体已经被读取到内存中(基于缓冲区大小(,并且没有传输编码,那么可以返回HttpEntity.Strict,因为我们已经完成了所有的工作。否则将返回一个HttpEntity.DefaultHttpEntity.Chunked

在最后一个catch中,如果您将HttpEntity作为服务器响应的一部分(例如在complete指令中(,那么服务器可能会超时,而不必消耗实体。在这种情况下,您可以使用withRequestTimeoutResponse指令来使用响应。

最新更新