Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Evil Martians

Slide 4

Slide 4 text

Evil Martians

Slide 5

Slide 5 text

What is Action Cable?

Slide 6

Slide 6 text

Action Cable RailsConf 2015 April, 21

Slide 7

Slide 7 text

Action Cable RailsConf 2015

Slide 8

Slide 8 text

Action Cable in a Nutshell Server Client WebSocket Client WebSocket stream C Broadcaster stream B stream A stream B channel X channel Y channel Z

Slide 9

Slide 9 text

Action Cable Channel class AnswersChannel < ApplicationCable::Channel def subscribed reject_subscription unless current_user.admin? end def follow(params) stream_from "questions/#{params['id']}" end end

Slide 10

Slide 10 text

The Good Parts

Slide 11

Slide 11 text

Good Parts • Easy configuration

Slide 12

Slide 12 text

Good Parts • Easy configuration • Application logic access through channels

Slide 13

Slide 13 text

Good Parts • Easy configuration • Application logic access through channels • JavaScript client that just works

Slide 14

Slide 14 text

Bad Parts?

Slide 15

Slide 15 text

Performance

Slide 16

Slide 16 text

Memory Cable

Slide 17

Slide 17 text

Memory Cable 20k connections MB 0 375 750 1 125 1 500 1 875 2 250 2 625 3 000 Go Erlang ActionCable (2x) ActionCable (16x)

Slide 18

Slide 18 text

WebSocket Shootout

Slide 19

Slide 19 text

WebSocket Shootout Client Server broadcast to all message send message back

Slide 20

Slide 20 text

WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s 6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Go Erlang ActionCable Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)

Slide 21

Slide 21 text

WebSocket Shootout

Slide 22

Slide 22 text

Testing

Slide 23

Slide 23 text

Testing Cable

Slide 24

Slide 24 text

Extensibility

Slide 25

Slide 25 text

• Server Abstraction Extended Cable

Slide 26

Slide 26 text

• Server Abstraction • Protocol Extensions (e.g. serialization, authentication, presence feature) Extended Cable

Slide 27

Slide 27 text

Other • Fallbacks / Transport • Rails-ness • Consistency

Slide 28

Slide 28 text

Consistency

Slide 29

Slide 29 text

Consistency?

Slide 30

Slide 30 text

How to Make it Better?

Slide 31

Slide 31 text

Testing Cable , 2016

Slide 32

Slide 32 text

Testing Cable class ServiceTest < ActionCable::TestCase def test_assert_transmited_message Service.broadcast 'messages', 'hi!' assert_broadcast_on('messages', text: 'hi!') end def test_assert_broadcast_on_again assert_broadcast_on('messages','h!') do Service.broadcast 'messages', text: 'h!' end end end

Slide 33

Slide 33 text

Testing Cable class ChannelTest < ActionCable::Channel::TestCase def test_subscribed_with_room_number subscribe room_number: 1 assert subscription.confirmed? assert "chat_1", streams.last end def test_perform_speak subscribe room_number: 1 perform :speak, message: "Hello" assert_equal "Hello", transmissions.last["message"]["text"] end end

Slide 34

Slide 34 text

PRs Cable

Slide 35

Slide 35 text

PRs Cable

Slide 36

Slide 36 text

AnyCable

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Server Channels Streams Client (Protocol) Action Cable AnyCable

Slide 39

Slide 39 text

Server Channels Streams Client (Protocol) Separation of Concerns Action Cable AnyCable

Slide 40

Slide 40 text

AnyCable

Slide 41

Slide 41 text

gRPC

Slide 42

Slide 42 text

gRPC = Google RPC

Slide 43

Slide 43 text

gRPC = Universal RPC Framework

Slide 44

Slide 44 text

gRPC = protobuf + HTTP/2

Slide 45

Slide 45 text

AnyCable Servers anycable-go erlycable

Slide 46

Slide 46 text

Memory Cable 20k connections MB 0 500 1 000 1 500 2 000 2 500 3 000 3 500 4 000 anycable-go erlycable ActionCable

Slide 47

Slide 47 text

Action Cable CPU

Slide 48

Slide 48 text

anycable-go CPU

Slide 49

Slide 49 text

erlycable CPU

Slide 50

Slide 50 text

WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s 6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 ActionCable anycable-go erlycable Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)

Slide 51

Slide 51 text

Compatibility Feature Status Connection Identifiers + Connection Request (cookies, params) + Disconnect Handling + Subscribe to channels + Parameterized subscriptions + Unsubscribe from channels + Subscription Instance Variables - Performing Channel Actions + Streaming + Custom stream callbacks - Broadcasting +

Slide 52

Slide 52 text

Action Cable Channel class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{chat_id}" do |msg| if msg['sent_at'].present? delay = Time.now.to_f - msg['sent_at'] logger.info "Message delay #{delay}s" end transmit msg end end end

Slide 53

Slide 53 text

PRs Cable

Slide 54

Slide 54 text

WebSocket Shootout Broadcast RTT 0s 1s 2s 3s 4s 5s 6s 7s 8s 9s 10s Number of connections 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 ActionCable Patch 1 Running on AWS EC2 c3.4xlarge (16 vCPU, 30 GiB RAM)

Slide 55

Slide 55 text

Where To anycable.io github.com/anycable twitter.com/any_cable gitter.im/anycable

Slide 56

Slide 56 text

PRs Cable

Slide 57

Slide 57 text

Server Adapter # config/application.rb 
 # specify server adapter config.action_cable.server = :plezi # or config.action_cable.server = :any_cable

Slide 58

Slide 58 text

plezi.io github.com/boazsegev/iodine Plezi

Slide 59

Slide 59 text

LiteCable

Slide 60

Slide 60 text

• Rails-free Action Cable • No deps (even ActiveSupport) • Compatible with AnyCable LiteCable

Slide 61

Slide 61 text

LiteCable module Chat # ... class Channel < LiteCable::Channel::Base identifier :chat def subscribed stream_from "chat_#{chat_id}" end end end run Rack::Builder.new do map '/cable' do use LiteCable::Server::Middleware, connection_class: Chat::Connection run proc { |_| [200, {}, ['']] } end end

Slide 62

Slide 62 text

LiteCable github.com/palkan/litecable

Slide 63

Slide 63 text

• Testing Support PRs • AnyCable for Performance • LiteCable for non-Rails • ACLI for development/testing What We Have

Slide 64

Slide 64 text

• Action Cable CLI • mRuby • Download'n'Run ACLI

Slide 65

Slide 65 text

ACLI

Slide 66

Slide 66 text

What's Next?

Slide 67

Slide 67 text

History Stream class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{id}", history: { time: 5.minutes } end end class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{chat_id}", history: { size: 100 } end end

Slide 68

Slide 68 text

Presence class ChatChannel < ApplicationCable::Channel def subscribed stream_from "chat_#{id}", presence: { user_id: user_id } end end // js client cable.subscriptions.create( { channel: 'chat', id: roomId }, { presenceUpdated: function(diff) { … } } )

Slide 69

Slide 69 text

cult of martians.com

Slide 70

Slide 70 text

Let's make Action Cable suck less! Vladimir Dementyev evilmartians.com @palkan @palkan_tula