Spec-Zone.ru › Ruby on Rails 7.1

модуль ActionController::Streaming

Потоковая передача данных в Action Controller

Позволяет передавать представления клиенту по мере их рендеринга.

По умолчанию Rails рендерит представления, сначала рендеринга шаблона, а затем макета. Ответ отправляется клиенту после рендеринга всего шаблона, выполнения всех запросов и обработки макета.

Потоковая передача изменяет порядок рендеринга, сначала рендеринга макета, а затем каждой части макета по мере их обработки. Это позволяет быстро передать заголовок HTML (который обычно находится в макете) клиенту, что позволяет загружать JavaScripts и стили раньше, чем обычно.

Некоторые промежуточные ПО Rack могут не работать, и вам нужно быть осторожным при потоковой передаче. Более подробная информация об этом приведена ниже, см. раздел Промежуточное ПО в Streaming.

Потоковую передачу можно легко добавить в шаблон, для этого необходимо передать параметр :stream в render

class PostsController
  def index
    @posts = Post.all
    render stream: true
  end
end

Когда использовать потоковую передачу

Потоковая передача может быть излишней для лёгких действий, таких как new или edit. Реальная польза потоковой передачи проявляется при ресурсоёмких действиях, которые, например, выполняют множество запросов к базе данных.

В таких действиях вы хотите отложить выполнение запросов как можно дольше. Например, представьте следующее действие dashboard

def dashboard
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
end

Большинство запросов в данном случае выполняются в контроллере. Для получения выгоды от потоковой передачи вам следует переписать его следующим образом:

def dashboard
  # Allow lazy execution of the queries
  @posts = Post.all
  @pages = Page.all
  @articles = Article.all
  render stream: true
end

Обратите внимание, что :stream работает только с шаблонами. Рендеринг :json или :xml с :stream не сработает.

Взаимодействие между макетом и шаблоном

При потоковой передаче рендеринг происходит сверху вниз, а не изнутри наружу. Rails начинает с макета, а шаблон рендерится позже, когда достигается его yield.

Это означает, что если ваше приложение в настоящее время полагается на переменные экземпляра, установленные в шаблоне, которые используются в макете, они не будут работать после перехода на потоковую передачу. Правильный способ взаимодействия между макетом и шаблоном, независимо от того, используете ли вы потоковую передачу или нет, заключается в использовании content_for, provide, и yield

Рассмотрим простой пример, где макет ожидает, что шаблон сообщит, какой заголовок использовать:

<html>
  <head><title><%= yield :title %></title></head>
  <body><%= yield %></body>
</html>

В шаблоне вы будете использовать content_for для указания заголовка:

<%= content_for :title, "Main" %>
Hello

И конечным результатом будет:

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

Однако, если content_for вызывается несколько раз, конечный результат будет содержать все вызовы, соединённые вместе. Например, если у нас есть следующий шаблон:

<%= content_for :title, "Main" %>
Hello
<%= content_for :title, " page" %>

Конечным результатом будет:

<html>
  <head><title>Main page</title></head>
  <body>Hello</body>
</html>

Это означает, что если у вас yield :title в макете, и вы хотите использовать потоковую передачу, вам нужно будет рендерить весь шаблон (и, в конечном итоге, выполнить все запросы) перед передачей заголовка и всех ресурсов, что сводит на нет цель потоковой передачи. В качестве альтернативы, вы можете использовать помощник provide, который делает то же самое, что и content_for, но сообщает макету прекратить поиск других записей и продолжить рендеринг.

Например, шаблон выше, используя provide будет:

<%= provide :title, "Main" %>
Hello
<%= content_for :title, " page" %>

Приводя к:

<html>
  <head><title>Main</title></head>
  <body>Hello</body>
</html>

Таким образом, при потоковой передаче необходимо правильно проверить свои шаблоны и выбрать, когда использовать provide и content_for

См. также ActionView::Helpers::CaptureHelper для получения дополнительной информации.

Заголовки, куки, сессия и всплывающие уведомления

При потоковой передаче HTTP-заголовки отправляются клиенту непосредственно перед рендерингом первой строки. Это означает, что изменение заголовков, куки, сессии или всплывающих уведомлений после начала рендеринга шаблона не будет передано клиенту.

Промежуточное ПО

Промежуточное ПО, которому необходимо манипулировать телом, не будет работать с потоковой передачей. Вам следует отключать это промежуточное ПО при потоковой передаче в режиме разработки или производства. Например, Rack::Bug не будет работать при потоковой передаче, так как ему нужно вставлять содержимое в тело HTML.

Также Rack::Cache не будет работать с потоковой передачей, так как оно ещё не поддерживает потоковую передачу тел. При потоковой передаче Cache-Control автоматически устанавливается в значение «no-cache».

Ошибки

Что касается потоковой передачи, обработка исключений становится немного сложнее. Это происходит потому, что часть шаблона уже была рендерена и передана клиенту, что делает невозможным рендеринг всей страницы с ошибкой.

В настоящее время при возникновении исключения в режиме разработки или производства Rails автоматически передаст клиенту:

"><script>window.location = "/500.html"</script></html>

Первые два символа (">) необходимы в случае возникновения исключения во время рендеринга атрибутов для данного тега. Вы можете проверить истинную причину исключения в своём логгере.

Поддержка веб-серверов

Не все веб-серверы поддерживают потоковую передачу «из коробки». Вам необходимо проверить инструкции для каждого из них.

Unicorn

Unicorn поддерживает потоковую передачу, но требует настройки. Для этого нужно создать конфигурационный файл следующим образом:

# unicorn.config.rb
listen 3000, tcp_nopush: false

И использовать его при инициализации:

unicorn_rails --config-file unicorn.config.rb

Вы также можете настроить другие параметры, такие как :tcp_nodelay.

Для получения дополнительной информации, пожалуйста, обратитесь к документации.

Если вы используете Unicorn с NGINX, вам может потребоваться настроить NGINX. Потоковая передача должна работать «из коробки» с Rainbows.

Passenger

Phusion Passenger с NGINX предлагает два механизма потоковой передачи «из коробки».

  1. Механизм буферизации ответов NGINX, который зависит от значения параметра passenger_buffer_response (по умолчанию «выкл.»).

  2. Система буферизации Passenger, которая всегда включена независимо от значения passenger_buffer_response.

Когда passenger_buffer_response включено, потоковая передача осуществляется на уровне NGINX, который ожидает, пока приложение закончит отправку ответа клиенту.

Для получения дополнительной информации, пожалуйста, обратитесь к документации.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API