Як використовувати solid-cable
для Turbo Broadcast
1. Додайте гем solid-cable
до вашого Gemfile:
gem 'solid-cable'
Потім виконайте команду:
bundle install
Згенеруйте міграцію для зберігання повідомлень solid-cable-message
в db/migrate/20241217100954createsolidcablemessages_table.rb. Тут я додав таблицю solid cable до тієї бази даних, яку ми вже використовуємо.
class CreateSolidCableMessagesTable < ActiveRecord::Migration[7.2]
def change
create_table :solid_cable_messages do |t|
t.binary :channel, limit: 1024, null: false
t.binary :payload, limit: 536_870_912, null: false
t.datetime :created_at, null: false
t.bigint :channel_hash, null: false
t.index :channel, name: "index_solid_cable_messages_on_channel"
t.index :channel_hash, name: "index_solid_cable_messages_on_channel_hash"
t.index :created_at, name: "index_solid_cable_messages_on_created_at"
end
end
end
Оновіть конфігураційні файли Rails:
Замість стандартної конфігурації Action Cable використовуйте solid-cable
.
Приклад: config/cable.yml
виглядатиме наступним чином:
development:
adapter: solid_cable
channel_prefix: rails_4_4sa_development
polling_interval: 0.1.seconds
message_retention: 1.day
test:
adapter: solid_cable
channel_prefix: rails_4_4sa_test_cable
production:
adapter: solid_cable
channel_prefix: <%= ENV['MYSQL_DATABASE'] %>
polling_interval: 0.1.seconds
message_retention: 1.day
У файлі
routes.rb
Rails.application.routes.draw do
mount ActionCable.server => '/cable'
end
У файлі
config/database.yml
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root
development:
<<: *default
database: rails_4_4sa_development
production:
<<: *default
username: <%= ENV['MYSQL_USERNAME'] %>
password: <%= ENV['MYSQL_PASSWORD'] %>
database: <%= ENV['MYSQL_DATABASE'] %>
host: <%= ENV['MYSQL_ADDRESS'] %>
strict: false
sslmode: 'verify-full'
sslrootcert: /app/rdscerts/rds-combined-ca-bundle.pem
sslca: /app/rdscerts/rds-combined-ca-bundle.pem
Налаштуйте трансляції Turbo Streams:
Turbo Streams використовують Action Cable для передачі оновлень у реальному часі до клієнтів. З solid-cable
цей процес залишається незмінним.
Приклад: трансляція оновлень у Rails:
# У вашому контролері Rails, моделі або worker/job
Turbo::StreamsChannel.broadcast_replace_to(
"posts",
target: "post_#{post.id}",
partial: "posts/post",
locals: { post: post }
)
<%= render partial: "post", locals: { post: post } %>
З усіма вищезгаданими кроками додаток Rails працює у розробці. Тепер давайте розглянемо налаштування для продакшн середовища. Почнемо з Що таке upstream сервер? Наприклад, у типовому налаштуванні Ruby on Rails:
- Клієнт: Браузер або будь-який HTTP клієнт робить запит до сервера Nginx.
- Nginx: Виконує роль зворотного проксі. Він перенаправляє запит до upstream сервера.
- Upstream сервер: У вашому випадку, ймовірно, сервер Puma, який обробляє запит і генерує відповідь.
Як Nginx визначає upstream сервери
У конфігурації Nginx upstream сервери визначаються за допомогою директиви upstream
, часто в налаштуваннях балансування навантаження.
Приклад:
upstream puma {
server 127.0.0.1:3000; # Puma сервер на localhost, порт 3000
}
Тут:
- puma
— це назва групи upstream серверів.
- 127.0.0.1:3000
— це реальна адреса та порт, на якому працює Puma.
Чому використовувати Nginx як проксі до upstream серверів?
- Балансування навантаження: Nginx може розподіляти запити між кількома upstream серверами.
- Безпека: Nginx може обробляти завершення HTTPS, захищаючи upstream сервер.
3.
Продуктивність: Nginx може кешувати статичні ресурси і зменшити навантаження на upstream сервер. - Підтримка WebSocket: Як у вашому прикладі, Nginx може полегшити з’єднання WebSocket з upstream сервером.
У вашій конкретній конфігурації upstream сервером є сервер Puma, який обробляє ваше Rails додаток.
Нижче наведена конфігурація Nginx для увімкнення ActionCable у продакшн сервері Nginx. Ви можете додати нижченаведену конфігурацію Nginx, і ваше додаток буде готове до роботи.
location /cable {
proxy_pass http://puma/cable;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
# Збільшуємо таймаут для довготривалих з’єднань WebSocket
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
Розберемо, що робить кожен рядок у блоці location /cable
:
1. location /cable {
Визначає блок локації в конфігурації Nginx, який обробляє запити до /cable
, зазвичай використовуваний для WebSocket з’єднань у Ruby on Rails додатку з використанням Action Cable.
2. proxy_pass http://puma/cable;
Перенаправляє вхідні запити до upstream сервера (в цьому випадку, сервер Puma) на вказаний кінцевий шлях /cable
.
puma
ймовірно визначений як upstream сервер у конфігурації Nginx.
3. proxy_http_version 1.1;
Гарантує, що Nginx використовує HTTP/1.1 для проксованих запитів. Це необхідно для WebSocket з’єднань, оскільки HTTP/1.1 підтримує заголовок Upgrade
, який потрібен для WebSocket.
4. proxy_set_header Upgrade $http_upgrade;
Встановлює заголовок Upgrade
у запиті зі значенням $http_upgrade
, яке Nginx автоматично визначає з вхідного WebSocket запиту.
- Цей заголовок вказує на перехід протоколу з HTTP на WebSocket.
5. proxy_set_header Connection "upgrade";
Встановлює заголовок Connection
в значення upgrade
. Це гарантує, що буде запитано оновлення протоколу WebSocket при проксуванні запиту.
6. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Додає оригінальну IP адресу клієнта до заголовка X-Forwarded-For
.
- Це допомагає upstream серверу ідентифікувати фактичну IP адресу клієнта, навіть коли запити проходять через кілька проксі.
7. proxy_set_header Host $http_host;
Встановлює заголовок Host
в значення заголовка Host
вхідного запиту.
- Це гарантує, що upstream сервер побачить правильну інформацію про хост.
8. proxy_redirect off;
Відключає автоматичне переписування URL в редиректах, що надходять від upstream сервера.
- Це корисно для збереження оригінальної структури URL.
9. proxy_set_header X-Real-IP $remote_addr;
Додає реальну IP адресу клієнта в заголовок X-Real-IP
.
- Ще один спосіб передати IP клієнта на upstream сервер.
10. proxy_set_header X-Forwarded-Proto $scheme;
Встановлює заголовок X-Forwarded-Proto
в схему (http
або https
), яку використовував клієнт.
- Це допомагає upstream серверу визначити, чи був оригінальний запит зроблений через HTTP чи HTTPS.
11. proxy_read_timeout 3600s;
Це опціонально. Встановлює максимальний час, який Nginx чекає на відповідь від upstream сервера, перш ніж закрити з’єднання.
- Значення
3600s
(1 година) високе, щоб підтримувати довготривалі з’єднання WebSocket.
12. proxy_send_timeout 3600s;
Це опціонально. Встановлює максимальний час, який Nginx чекає на передачу даних від клієнта, перш ніж закрити з’єднання.
- Також встановлено на 1 годину для підтримки довготривалих з’єднань WebSocket.
Перекладено з: Rails7 app production ready with WebSocket for TurboBroadcast