iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
1
自我挑戰組

關於 Ruby on Rails 的那些事系列 第 21

Day 21 - RoR 如何實現即時通訊「ActionCable」- 上集

  • 分享至 

  • xImage
  •  

前兩天介紹了輪詢、WebSocket,雖然不是很完整,但有稍稍了解一點即時通訊不是像我們平常想得理所當然!而今天要講的是 Action Cable 的背後原理,以及在 Rails 應用中如何通過WebSocket 實現即時功能。

Publish–subscribe pattern

Actioncable 是一個 Pub/Sub 模型 (發布/訂閱) + WebSocket 的 Ruby 框架,可以讓 Rails 透過websocket,實現即時通訊。

Pub/Sub 設計模式是即時通訊很常使用的架構,將訊息的傳送者、接收者拆分為發布方、訂閱方。而發布方可以將訊息傳送給許多訂閱方。

使用 redis 資料庫

全名 REmote DIctionary Server,屬於 NOSQL 家族中的一個成員。
NOSQL (Not Only SQL) 分散式非關聯式資料庫的統稱,不同於傳統的關聯式資料庫,ex: MySQL、PostgreSQL。

是快速的開放原始碼記憶體內鍵值資料存放區,可做為資料庫、快取、訊息代理程式和佇列使用。目前 Redis 的回應時間低於一毫秒,使遊戲、金融服務、醫療保健等領域的即時應用程式每秒處理數百萬個請求。Redis 是用於快取、工作階段管理、遊戲、排行榜、即時分析、地理空間、叫車、聊天/簡訊、媒體串流和發佈/訂閱應用程式的熱門選項。

實作 ActionCable

1. 開啟終端機,建立新的 rails 專案:

(會想要用 PG 是因為打算部署在 Heroku 上,因為預設的情況下,rails 會採用 SQLite )

$ rails new chatchat database: postgresql

小提醒:前面的 $ 表示為終端機指令,不用輸入喔!

2. ActionCable 使用redis

要進行修改的檔案為 config/cable.yml

修改前:

development:
  adapter: async

test:
  adapter: test

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: chatchat_production

修改後:

development:
  adapter: redis
  url: redis://localhost:6379/1

test:
  adapter: test

production:
  adapter: redis
  url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
  channel_prefix: chatchat_production

在專案中安裝

(Mac)使用 Homebrew 安裝 Redis 會減少大量的安裝時間。
詳細安裝過程可以請 Google 協助!

$ brew install redis

可能會要你先 update homebrew。

開機即自動啟動 Redis 指令(之後就不怕忘記啟動啦~)

$ ln -sfv /usr/local/opt/redis/*.plist ~/Library/LaunchAgents

在專案中引入套件

# gemfile.rb
gem 'redis', '~> 3.3', '>= 3.3.1'
$ bundle install

3. 長出一個 channel room

$ rails g channel room

執行結果如下

來看看 rails 幫我們長了哪些東西

產生的測試檔就不管了,主要有以下重點檔案:

app/channels/room_channel.rb

class RoomChannel < ApplicationCable::Channel
  def subscribed
    # stream_from "some_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end

app/javascript/channels/consumer.js

// Action Cable provides the framework to deal with WebSockets in Rails.
// You can generate new channels where WebSocket features live using the `rails generate channel` command.

import { createConsumer } from "@rails/actioncable"

export default createConsumer()

app/javascript/channels/index.js

// Load all the channels within this directory and all subdirectories.
// Channel files must be named *_channel.js.

const channels = require.context('.', true, /_channel\.js$/)
channels.keys().forEach(channels)

app/javascript/channels/room_channel.js

import consumer from "./consumer"

consumer.subscriptions.create("RoomChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    // Called when there's incoming data on the websocket for this channel
  }
});

明天來解釋這個過程做了什麼事?

參考資料:
railsguides-Action Cable Overview
rubyonrails-api
實戰聖經 - Action Cable 即時通訊
AWS - 什麼是 Redis?
Rails Tutorial | Action Cable Basics in Rails 6

學無止盡,每天都要進步一點點!


上一篇
Day 20 - 關於「即時更新」- WebSocket
下一篇
Day 22 - RoR 如何實現即時通訊「ActionCable」- 下集
系列文
關於 Ruby on Rails 的那些事30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言