В akka-http должны ли объекты ответа потребляться в приемнике, если ответ отличается от 200?

На этом http://doc.akka.io/docs/akka/2.4.9/scala/http/client-side/request-level.html#Future-Based_Variant внизу есть предупреждение:

Обязательно используйте объекты ответа dataBytes:Source[ByteString,Unit], например, подключив его к приемнику (например, response.entity.dataBytes.runWith(Sink.ignore), если вам не нужен объект ответа), поскольку в противном случае 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)
  }

person michael g    schedule 19.08.2016    source источник


Ответы (1)


Сущность ответа всегда должна использоваться, однако на практике ответы об ошибках обычно имеют тип HttpEntity.Strict, и отказ от их использования не вызовет проблем с обратным давлением.

Для заинтересованных, начиная с Akka 2.4.9, это поведение взято из SlotProcessor.running, где он оборачивает HttpEntity с помощью HttpEntity.captureTermination. Эта обертка используется, чтобы сигнализировать о том, что ответ был использован, и, таким образом, обеспечивает правильные сигналы обратного давления. Для HttpEntity.Strict, поскольку тело объекта уже находится в памяти, метод captureTermination вернет Future.success(()), тогда как другие типы будут обертывать Source и возвращать Future, который завершается, когда базовый Source завершается.

Что касается возвращаемого типа HttpEntity, то с точки зрения API нет никаких гарантий, что определенные ответы будут HttpEntity.Strict, поэтому рекомендуется всегда использовать ответ. HttpResponseParser анализирует ответы. Как я понимаю, при чтении ответа, если тело уже прочитано в память (на основе размера буфера) и нет кодировки передачи, то может быть возвращено HttpEntity.Strict, так как мы уже сделали всю работу. В противном случае будет возвращено HttpEntity.Default или HttpEntity.Chunked.

При последнем улове, если вы используете HttpEntity как часть ответа сервера (например, в директиве complete), сервер может истечь тайм-аут и не беспокоиться о потреблении объекта. В этом случае вы можете использовать директиву withRequestTimeoutResponse для получения ответа.

person leachbj    schedule 20.08.2016
comment
спасибо, у вас есть ссылка на место в документации или исходном коде, где вы сделали этот вывод? - person michael g; 23.08.2016
comment
Я обновил ответ, чтобы включить ссылки на код. Надеюсь, это поможет! - person leachbj; 23.08.2016
comment
спасибо за глубокое погружение. Из исходного кода мне до сих пор не ясно, как мы можем быть уверены, что ответы об ошибках имеют тип HttpEntity.Strict и, следовательно, все тело сущности находится в памяти (похоже, это центральная часть всего этого). В документ для HttpEntity. Учитывая это, на всякий случай я буду использовать response.entity для всех ответов об ошибках. - person michael g; 23.08.2016