Action Cable
2016/12/13 1
Action Cable
• ActionCableとは
• WebSocketsとRailsを統合するためのフレームワーク
• RailsのRESTとWebSocketのシームレスな統合
• 複数のクライアントとPub/Sub通信
http://railsguides.jp/action_cable_overview.html
• 主な利用例
• ライブチャット
• サイトのお知らせや警告をリアルタイム表示
• 特徴
• WebSocket
• Redisが必要?(subscription adapter に radis を利用する場合必要)
2016/12/13 2
WebSocket
• 双方向通信を実現するプロトコル
• HTTPでコネクション確立、WebSocket プロトコルへ upgrade
• Blocking I/Oを持つWebサーバとは相性が悪い
• Unicorn ×
• Puma, Thin 〇
• Puma や Thin のようなスレッドサーバを使っている場合は、
アプリ内でActionCableの実装を動かす事ができる(おそらく subscription adapter: async)
2016/12/13 3
Sample
• ごくシンプルなチャットの実装を紹介します
• 構成(ほとんど rails new のまま)
• Ruby 2.3.3
• Ruby On Rails 5.0.0.1
• Puma (rails5 default)
• DB未使用
• Redis未使用(development)
2016/12/13 4
Configurations
• Action Cable has three required configurations
• Subscription Adapter
• Allowed Request Origins
• Cable Server URL
2016/12/13 5
Configurations
• subscription adapter
• config/cable.yml
• AdapterにPostgreSQLやRedis等 Pub/Subの機能を持ったプロセスを設定可能
2016/12/13 6
development:
adapter: async
test:
adapter: async
production:
adapter: redis
url: redis://localhost:6379/1
Configurations
• allowed request origins
• Action Cableは指定されていない送信元からのリクエストを受け付けません
設定で許可する必要があります
2016/12/13 7
config.action_cable.allowed_request_origins = ['http://rubyonrails.com', %r{http://ruby.*}]
config.action_cable.disable_request_forgery_protection = true
Configurations
• Cable Server URL(Consumer Configuration)
• Action Cable のサーバーURLをclientサイドに提供する必要があります
(クライアントのJavaScriptの中でサーバーサイドのURLを指定する必要があります)
2016/12/13 8
config.action_cable.url = "ws://example.com:28080"
※ default
Rails.application.config.action_cable
=> {
:mount_path=> "/cable",
:disable_request_forgery_protection => true,
:allowed_request_origins => http://localhost:3000
}
Implement room channel
• Roomチャンネルの作成
2016/12/13 9
# rails g channel room speak
Running via Spring preloader in process 12363
Expected string default value for '--jbuilder'; got true (boolean)
create app/channels/room_channel.rb
identical app/assets/javascripts/cable.js
create app/assets/javascripts/channels/room.coffee
Implement room channel
• Roomチャンネルの作成
2016/12/13 10
# rails g channel room speak
Running via Spring preloader in process 12363
Expected string default value for '--jbuilder'; got true (boolean)
create app/channels/room_channel.rb
identical app/assets/javascripts/cable.js
create app/assets/javascripts/channels/room.coffee
Implement room channel
• Roomチャンネルの作成
• app/channels/room_channel.rb
• WebSocketサーバー ⇒ クライアント
• app/assets/javascripts/channels/room.coffee
• クライアント ⇒ WebSocketサーバー
2016/12/13 11
# rails g channel room speak
Running via Spring preloader in process 12363
Expected string default value for '--jbuilder'; got true (boolean)
create app/channels/room_channel.rb
identical app/assets/javascripts/cable.js
create app/assets/javascripts/channels/room.coffee
Implement room channel
• app/channels/room_channel.rb
2016/12/13 12
class RoomChannel < ApplicationCable::Channel
def subscribed
stream_from "room_channel“
end
def unsubscribed
# Any cleanup needed when channel is unsubscribed
end
def speak(data)
ActionCable.server.broadcast 'room_channel', message: data['message']
end
end
Implement room channel
• app/assets/javascripts/channels/room.coffee
2016/12/13 13
App.room = App.cable.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
h = $("<p>" + data["message"] + "</p>")
$(".messages").append(h)
$("input.speak").val("")
speak: (data)->
@perform 'speak', data
使ってみて
• 簡単にできそうだが…まだまだ資料不足
• subscription adapter に関して等々
• 欠点について
• サーバーで管理されている接続状態の情報が失われると、クライアントが切断されている間に公開されたメッ
セージが失われてしまう
• 待ち時間がある
• 突然のエラーで接続状態の情報が破損する
• RedisのPub/Subを利用する場合、Redisが止まると、ActionCabelも止まる
• ACK/NACKがない(ActionCableに送ったメッセージが届いたかどうかを確認する機能がない
• メッセージの順序が保証されない
• プラットフォーム相互運用性がない
引用元:
https://blog.ably.io/rails-5-actioncable-the-good-and-bad-parts-1b56c3b31404
https://www.transnet.ne.jp/2016/05/18/colnrrails-
5%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9Factioncable%E3%81%AE%E5%88%A9%E7%82%B9%E3%81%A8%E6%AC%A0
%E7%82%B9%E3%82%B3%E3%83%A9%E3%83%A0/
2016/12/13 14

ウェブチップス勉強会 Action cable

  • 1.
  • 2.
    Action Cable • ActionCableとは •WebSocketsとRailsを統合するためのフレームワーク • RailsのRESTとWebSocketのシームレスな統合 • 複数のクライアントとPub/Sub通信 http://railsguides.jp/action_cable_overview.html • 主な利用例 • ライブチャット • サイトのお知らせや警告をリアルタイム表示 • 特徴 • WebSocket • Redisが必要?(subscription adapter に radis を利用する場合必要) 2016/12/13 2
  • 3.
    WebSocket • 双方向通信を実現するプロトコル • HTTPでコネクション確立、WebSocketプロトコルへ upgrade • Blocking I/Oを持つWebサーバとは相性が悪い • Unicorn × • Puma, Thin 〇 • Puma や Thin のようなスレッドサーバを使っている場合は、 アプリ内でActionCableの実装を動かす事ができる(おそらく subscription adapter: async) 2016/12/13 3
  • 4.
    Sample • ごくシンプルなチャットの実装を紹介します • 構成(ほとんどrails new のまま) • Ruby 2.3.3 • Ruby On Rails 5.0.0.1 • Puma (rails5 default) • DB未使用 • Redis未使用(development) 2016/12/13 4
  • 5.
    Configurations • Action Cablehas three required configurations • Subscription Adapter • Allowed Request Origins • Cable Server URL 2016/12/13 5
  • 6.
    Configurations • subscription adapter •config/cable.yml • AdapterにPostgreSQLやRedis等 Pub/Subの機能を持ったプロセスを設定可能 2016/12/13 6 development: adapter: async test: adapter: async production: adapter: redis url: redis://localhost:6379/1
  • 7.
    Configurations • allowed requestorigins • Action Cableは指定されていない送信元からのリクエストを受け付けません 設定で許可する必要があります 2016/12/13 7 config.action_cable.allowed_request_origins = ['http://rubyonrails.com', %r{http://ruby.*}] config.action_cable.disable_request_forgery_protection = true
  • 8.
    Configurations • Cable ServerURL(Consumer Configuration) • Action Cable のサーバーURLをclientサイドに提供する必要があります (クライアントのJavaScriptの中でサーバーサイドのURLを指定する必要があります) 2016/12/13 8 config.action_cable.url = "ws://example.com:28080" ※ default Rails.application.config.action_cable => { :mount_path=> "/cable", :disable_request_forgery_protection => true, :allowed_request_origins => http://localhost:3000 }
  • 9.
    Implement room channel •Roomチャンネルの作成 2016/12/13 9 # rails g channel room speak Running via Spring preloader in process 12363 Expected string default value for '--jbuilder'; got true (boolean) create app/channels/room_channel.rb identical app/assets/javascripts/cable.js create app/assets/javascripts/channels/room.coffee
  • 10.
    Implement room channel •Roomチャンネルの作成 2016/12/13 10 # rails g channel room speak Running via Spring preloader in process 12363 Expected string default value for '--jbuilder'; got true (boolean) create app/channels/room_channel.rb identical app/assets/javascripts/cable.js create app/assets/javascripts/channels/room.coffee
  • 11.
    Implement room channel •Roomチャンネルの作成 • app/channels/room_channel.rb • WebSocketサーバー ⇒ クライアント • app/assets/javascripts/channels/room.coffee • クライアント ⇒ WebSocketサーバー 2016/12/13 11 # rails g channel room speak Running via Spring preloader in process 12363 Expected string default value for '--jbuilder'; got true (boolean) create app/channels/room_channel.rb identical app/assets/javascripts/cable.js create app/assets/javascripts/channels/room.coffee
  • 12.
    Implement room channel •app/channels/room_channel.rb 2016/12/13 12 class RoomChannel < ApplicationCable::Channel def subscribed stream_from "room_channel“ end def unsubscribed # Any cleanup needed when channel is unsubscribed end def speak(data) ActionCable.server.broadcast 'room_channel', message: data['message'] end end
  • 13.
    Implement room channel •app/assets/javascripts/channels/room.coffee 2016/12/13 13 App.room = App.cable.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 h = $("<p>" + data["message"] + "</p>") $(".messages").append(h) $("input.speak").val("") speak: (data)-> @perform 'speak', data
  • 14.
    使ってみて • 簡単にできそうだが…まだまだ資料不足 • subscriptionadapter に関して等々 • 欠点について • サーバーで管理されている接続状態の情報が失われると、クライアントが切断されている間に公開されたメッ セージが失われてしまう • 待ち時間がある • 突然のエラーで接続状態の情報が破損する • RedisのPub/Subを利用する場合、Redisが止まると、ActionCabelも止まる • ACK/NACKがない(ActionCableに送ったメッセージが届いたかどうかを確認する機能がない • メッセージの順序が保証されない • プラットフォーム相互運用性がない 引用元: https://blog.ably.io/rails-5-actioncable-the-good-and-bad-parts-1b56c3b31404 https://www.transnet.ne.jp/2016/05/18/colnrrails- 5%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9Factioncable%E3%81%AE%E5%88%A9%E7%82%B9%E3%81%A8%E6%AC%A0 %E7%82%B9%E3%82%B3%E3%83%A9%E3%83%A0/ 2016/12/13 14