在这个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)
}
答案 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.Chunked
或HttpEntity
。
在最后一次捕获时,如果您使用complete
作为服务器响应的一部分(例如在withRequestTimeoutResponse
指令中),那么服务器可能会超时并且不会费力消耗该实体。在这种情况下,您可以使用dojo.attr
指令来使用响应。