SlideShare a Scribd company logo
Rails
RabbitMQ
WebSockets
EventMachine
o wyprawie królika przez maszynkę do
gniazdka, czyli Event Machine w praktyce
grzegorz
bryliński
Ja
• opowiem wam o pewnym projekcie
• pisałem w PHP i już nie chcę (-:
• teraz piszę w Ruby
• i bardzo się staram, bo nie wiem kto siedzi
obok, a jak mówi chińskie przysłowie:
Zawsze pisz kod tak, jakby osoba która będzie
pracowała nad nim po tobie była psychopatycznym
mordercą, który wie gdzie mieszkasz.
Był sobie projekt
• Panel administracyjny z podstawową
funkcjonalnością
• RESTful API
• Serwer WebSocket
• Aplikacja mobilna dla iOS-a
Klient chciałby wiele…
…oczekiwania ↦ ∞
A może sobie pozwolić…
…stosownie do budżetu ↦ 0
Damy radę, ale…
• Niska ilość potrzebnych mendejsów, a więc…
• szybki development, a więc…
• prosta architektura, a więc…
• jednorodne środowisko, a więc…
Ein Reich Ruby dla wszystkich…
• Mniej języków, mniej problemów
• Panel administracyjny - RoR
• Serwer WS - Ruby
• Interfejs MQ - Ruby
Ruby on Rails
http://rubyonrails.org/
public function indexAction()
{
return $this->render('default/index.html.twig');
}
def index
end
czy…
!ruby albo zdrowie, wybór należy do ciebie…
RabbitMQ
• Message Broker
• po polsku: Mesedż Broker 😜
• po prostu działa ™
• Erlang, no trudno
• https://www.rabbitmq.com/
EventMachine
• implementuje wzorzec reaktora
• jest lekka i szybka
• cięższe zadania -> Deferrable
• https://github.com/eventmachine/
eventmachine
Bunny
• tunel do RabbitMQ
• prosty (bardzo)
• to już duży, dojrzały królik
• działa z… EM
• https://github.com/ruby-amqp/bunny
EM-WebSockets
• Serwer WebSocket w Ruby
• prosty (bardzo)
• działa z… EM
• deja vu, deja vu
• https://github.com/igrigorik/em-websocket
Nasz projekt
koćmy zatem…
Pętla główna
require "event_machine"
EventMachine.run do
definition_of_some_useful_handlers
end
Disclaimer:
prezentowany kod to złożona forma cyfrowego odwzorowania ludzkiej
myśli. Jest obszerny i skomplikowany, może też być niezrozumiały.
żart, przecież to Ruby
+= WebSockets
require "event_machine"
require "em-websocket"
server_config_hash = {host: "0", port: 8080}
EventMachine.run do
EM::WebSocket.run(server_config_hash) do |ws|
ws.onopen { |handshake| do_something_on_open(ws, handshake) }
ws.onmessage { |msg| do_something_else_on_message(ws, msg) }
ws.onclose { do_nothing_on_close(ws) }
ws.onerror { |error| definitely_do_nothing_on_error(error) }
end
end
Identyfikacja klienta?
def on_open(ws, handshake)
if user = User.for_token( handshake.query["token"] )
connection_pool.update(ws, user.id)
else
log "Open without a valid user. Foch..."
ws.close
end
rescue => exception
log "OPEN exception: #{exception}"
end
+= Bunny
require "event_machine"
require "bunny"
connection = Bunny.new
channel = connection.create_channel
queue = channel.queue("a_test_queue", durable: false)
EventMachine.run do
queue.subscribe(manual_ack: true, block: false) do
|delivery_info, properties, body|
message = JSON.parse(body) # it's smart and convenient to use JSON
do_magic_on(message) && channel.ack(delivery_info.delivery_tag)
end
end
+= Bunny
queue.subscribe(manual_ack: true, block: false) do …
o tym warto pamiętać
+= Timers
require "event_machine"
EventMachine.run do
EventMachine::PeriodicTimer.new(1) do
send_server_stats_to_manager_email
end
end
Razem prezentuje się…
require "event_machine"
require "bunny"
require "em-websocket"
counter = 0
server_config_hash = {host: "0", port: 8080}
connection = Bunny.new
channel = connection.create_channel
queue = channel.queue("a_test_queue", durable: false)
EventMachine.run do
EM::WebSocket.run(server_config_hash) do |ws|
ws.onopen { |handshake| do_something_on_open(ws, handshake) }
ws.onmessage { |msg| do_something_else_on_message(ws, msg) }
ws.onclose { do_nothing_on_close(ws) }
ws.onerror { |error| definitely_do_nothing_on_error(error) }
end
queue.subscribe(manual_ack: true, block: false) do |delivery_info, properties, body|
message = JSON.parse(body) # it's smart and convenient to use JSON
do_magic_on(message)
channel.ack(delivery_info.delivery_tag)
end
EventMachine::PeriodicTimer.new(1) do
send_server_stats_to_manager_email
end
end
Niewiele kodu,
który sporo robi
bo Facebook
sam się nie uzupełni
Tymczasem w aplikacji…
class Message
def push_to_bunny
$rabbit_session.publish_message(self.id)
end
end
Tyle wystarczy, żeby wysłać
naszą wiadomość
do kolejki. Ruby rulez (-:
Tadam!
• Działa
• Jest prosto
• Było szybko
• Będzie stabilnie
Obserwacje
• wyjątki dobrze jest obsługiwać w miejscu,
w którym się ich spodziewamy. EM
domyślnie je przechwytuje i tyle.
• nie należy serializować obiektów i
wrzucać ich do kolejek. Ale przecież nikt
tego nie robi. Robi?
Obserwacje…
• Bundler.require jest pożyteczny
• Obsługę poszczególnych sub-pętli dobrze
wrzucić do dedykowanych klas. Kod staje
się podatny na testowanie.
Dziękuję za uwagę
GitHub: http://goo.gl/jEopOq
email: grzegorz@tsh.io
Pytania?

More Related Content

PPTX
Architektura serwera gier online
PDF
Podstawy JavaScript | DreamLab Academy #7
ODP
[4Dev][Łódź] Jacek Jagieła - Czy server może mnie usłyszeć i się zreboot...
PPT
Mvc frontend-trug-02-2011
PDF
Jak ugryźć Ruby, żeby nie połamać zębów?
PDF
REvolution, czyli o bardziej obiektowym podejściu w Railsach
PDF
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
PDF
Gulp.js - alternatywa do Grunta
Architektura serwera gier online
Podstawy JavaScript | DreamLab Academy #7
[4Dev][Łódź] Jacek Jagieła - Czy server może mnie usłyszeć i się zreboot...
Mvc frontend-trug-02-2011
Jak ugryźć Ruby, żeby nie połamać zębów?
REvolution, czyli o bardziej obiektowym podejściu w Railsach
Developer mode on, czyli słów kilka o rbenv, rvm i ruby-ng
Gulp.js - alternatywa do Grunta

Viewers also liked (20)

PDF
Tester - przyjaciel czy wróg programisty?
PDF
Bitcoin - (nie)udany eksperyment?
PDF
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
PDF
Praktyczne porady na temat optymalizacji wydajności aplikacji tworzonych z u...
PDF
Znaki mocy dla laików – Programowanie funkcyjne w JavaScript
PDF
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
PDF
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
PDF
Bestiariusza wpisy wybrane
PDF
Red Green Hotfix – złudne poczucie bezpieczeństwa w testach
PDF
ReactPHP – reaktor jądrowy w PHP
PDF
Pi razy drzwi - o szacowaniu projektów
PDF
O Electronie słów kilka
PDF
Wielkie protokoły wielkich ludzi
PDF
Angular 2.0 – Kochaj albo rzuć!
PDF
PDF
PSR-7 - HTTP message interfaces
PDF
Design dla estetycznie ograniczonych
PDF
TDD w iOS
PDF
Deploy appki na iOS, czyli magia publikacji
Tester - przyjaciel czy wróg programisty?
Bitcoin - (nie)udany eksperyment?
Nie wszystko, co ubite, w ziemi zostaje. Wprowadzenie do Event Sourcing
Praktyczne porady na temat optymalizacji wydajności aplikacji tworzonych z u...
Znaki mocy dla laików – Programowanie funkcyjne w JavaScript
Pierwsza aplikacja na iOS, czyli z czym można się spotkać, co jest trudne i c...
Wprowadzenie do języka Swift, czyli nowe podejście do programowania aplikacji...
Bestiariusza wpisy wybrane
Red Green Hotfix – złudne poczucie bezpieczeństwa w testach
ReactPHP – reaktor jądrowy w PHP
Pi razy drzwi - o szacowaniu projektów
O Electronie słów kilka
Wielkie protokoły wielkich ludzi
Angular 2.0 – Kochaj albo rzuć!
PSR-7 - HTTP message interfaces
Design dla estetycznie ograniczonych
TDD w iOS
Deploy appki na iOS, czyli magia publikacji
Ad

Similar to O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce (20)

PPTX
Co nowego w VS 2013 dla programistów ASP.NET?
PPTX
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
PPTX
Budowa usług internetowych: SOAP, Websockets
PPTX
Jak zostać mobile deweloperem w 1 dzień
PPTX
Programowanie aplikacji dla Windows 8 (WinRT)
PDF
Space Wars Hack - Class #1
PDF
Developing native-like Windows application using JavaScript, SSE, eZ Platform...
PPTX
Jak podwoić wartość kodu .NET?
PPTX
Jak stworzyć udany system informatyczny
PDF
Jak łączyć mobile i desktop? Node.js w aplikacjach czasu rzeczywistego.
PDF
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
PDF
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
PDF
Xamarin.Forms - wprowadzenie
PPTX
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
PDF
Prostota i mozliwosci symfony2
PPTX
Iron Python I Dlr
ODP
Aplikacje internetowe (2010)
PPTX
PPTX
Windows Communication Foundation
PPSX
Webinar - Podstawy Node.js
Co nowego w VS 2013 dla programistów ASP.NET?
Tomasz Kopacz MTS 2012 Wind RT w Windows 8 i tzw aplikacje lob (line of busin...
Budowa usług internetowych: SOAP, Websockets
Jak zostać mobile deweloperem w 1 dzień
Programowanie aplikacji dla Windows 8 (WinRT)
Space Wars Hack - Class #1
Developing native-like Windows application using JavaScript, SSE, eZ Platform...
Jak podwoić wartość kodu .NET?
Jak stworzyć udany system informatyczny
Jak łączyć mobile i desktop? Node.js w aplikacjach czasu rzeczywistego.
Asynchroniczny PHP & komunikacja czasu rzeczywistego z wykorzystaniem websock...
Asynchroniczny PHP i komunikacja czasu rzeczywistego z wykorzystaniem websocketw
Xamarin.Forms - wprowadzenie
Mts 2013 tomasz kopacz - windows 8, office 365, workflow manager, windows a...
Prostota i mozliwosci symfony2
Iron Python I Dlr
Aplikacje internetowe (2010)
Windows Communication Foundation
Webinar - Podstawy Node.js
Ad

More from The Software House (20)

PDF
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
PDF
Uszanowanko Podsumowanko
PDF
Jak efektywnie podejść do certyfikacji w AWS?
PDF
O co chodzi z tą dostępnością cyfrową?
PDF
Chat tekstowy z użyciem Amazon Chime
PDF
Migracje danych serverless
PDF
Jak nie zwariować z architekturą Serverless?
PDF
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
PDF
Feature flags na ratunek projektu w JavaScript
PDF
Typowanie nominalne w TypeScript
PDF
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
PDF
Serverless Compose vs hurtownia danych
PDF
Testy API: połączenie z bazą danych czy implementacja w pamięci
PDF
Jak skutecznie read model. Case study
PDF
Firestore czyli ognista baza od giganta z Doliny Krzemowej
PDF
Jak utrzymać stado Lambd w ryzach
PDF
Jak poskromić AWS?
PDF
O łączeniu Storyblok i Next.js
PDF
Amazon Step Functions. Sposób na implementację procesów w chmurze
PDF
Od Figmy do gotowej aplikacji bez linijki kodu
Jak kraść miliony, czyli o błędach bezpieczeństwa, które mogą spotkać również...
Uszanowanko Podsumowanko
Jak efektywnie podejść do certyfikacji w AWS?
O co chodzi z tą dostępnością cyfrową?
Chat tekstowy z użyciem Amazon Chime
Migracje danych serverless
Jak nie zwariować z architekturą Serverless?
Analiza semantyczna artykułów prasowych w 5 sprintów z użyciem AWS
Feature flags na ratunek projektu w JavaScript
Typowanie nominalne w TypeScript
Automatyzacja tworzenia frontendu z wykorzystaniem GraphQL
Serverless Compose vs hurtownia danych
Testy API: połączenie z bazą danych czy implementacja w pamięci
Jak skutecznie read model. Case study
Firestore czyli ognista baza od giganta z Doliny Krzemowej
Jak utrzymać stado Lambd w ryzach
Jak poskromić AWS?
O łączeniu Storyblok i Next.js
Amazon Step Functions. Sposób na implementację procesów w chmurze
Od Figmy do gotowej aplikacji bez linijki kodu

O wyprawie królika przez maszynkę do gniazdka, czyli EventMachine w praktyce

  • 1. Rails RabbitMQ WebSockets EventMachine o wyprawie królika przez maszynkę do gniazdka, czyli Event Machine w praktyce grzegorz bryliński
  • 2. Ja • opowiem wam o pewnym projekcie • pisałem w PHP i już nie chcę (-: • teraz piszę w Ruby • i bardzo się staram, bo nie wiem kto siedzi obok, a jak mówi chińskie przysłowie: Zawsze pisz kod tak, jakby osoba która będzie pracowała nad nim po tobie była psychopatycznym mordercą, który wie gdzie mieszkasz.
  • 3. Był sobie projekt • Panel administracyjny z podstawową funkcjonalnością • RESTful API • Serwer WebSocket • Aplikacja mobilna dla iOS-a
  • 5. A może sobie pozwolić… …stosownie do budżetu ↦ 0
  • 6. Damy radę, ale… • Niska ilość potrzebnych mendejsów, a więc… • szybki development, a więc… • prosta architektura, a więc… • jednorodne środowisko, a więc…
  • 7. Ein Reich Ruby dla wszystkich… • Mniej języków, mniej problemów • Panel administracyjny - RoR • Serwer WS - Ruby • Interfejs MQ - Ruby
  • 8. Ruby on Rails http://rubyonrails.org/ public function indexAction() { return $this->render('default/index.html.twig'); } def index end czy… !ruby albo zdrowie, wybór należy do ciebie…
  • 9. RabbitMQ • Message Broker • po polsku: Mesedż Broker 😜 • po prostu działa ™ • Erlang, no trudno • https://www.rabbitmq.com/
  • 10. EventMachine • implementuje wzorzec reaktora • jest lekka i szybka • cięższe zadania -> Deferrable • https://github.com/eventmachine/ eventmachine
  • 11. Bunny • tunel do RabbitMQ • prosty (bardzo) • to już duży, dojrzały królik • działa z… EM • https://github.com/ruby-amqp/bunny
  • 12. EM-WebSockets • Serwer WebSocket w Ruby • prosty (bardzo) • działa z… EM • deja vu, deja vu • https://github.com/igrigorik/em-websocket
  • 14. Pętla główna require "event_machine" EventMachine.run do definition_of_some_useful_handlers end Disclaimer: prezentowany kod to złożona forma cyfrowego odwzorowania ludzkiej myśli. Jest obszerny i skomplikowany, może też być niezrozumiały. żart, przecież to Ruby
  • 15. += WebSockets require "event_machine" require "em-websocket" server_config_hash = {host: "0", port: 8080} EventMachine.run do EM::WebSocket.run(server_config_hash) do |ws| ws.onopen { |handshake| do_something_on_open(ws, handshake) } ws.onmessage { |msg| do_something_else_on_message(ws, msg) } ws.onclose { do_nothing_on_close(ws) } ws.onerror { |error| definitely_do_nothing_on_error(error) } end end
  • 16. Identyfikacja klienta? def on_open(ws, handshake) if user = User.for_token( handshake.query["token"] ) connection_pool.update(ws, user.id) else log "Open without a valid user. Foch..." ws.close end rescue => exception log "OPEN exception: #{exception}" end
  • 17. += Bunny require "event_machine" require "bunny" connection = Bunny.new channel = connection.create_channel queue = channel.queue("a_test_queue", durable: false) EventMachine.run do queue.subscribe(manual_ack: true, block: false) do |delivery_info, properties, body| message = JSON.parse(body) # it's smart and convenient to use JSON do_magic_on(message) && channel.ack(delivery_info.delivery_tag) end end
  • 18. += Bunny queue.subscribe(manual_ack: true, block: false) do … o tym warto pamiętać
  • 19. += Timers require "event_machine" EventMachine.run do EventMachine::PeriodicTimer.new(1) do send_server_stats_to_manager_email end end
  • 20. Razem prezentuje się… require "event_machine" require "bunny" require "em-websocket" counter = 0 server_config_hash = {host: "0", port: 8080} connection = Bunny.new channel = connection.create_channel queue = channel.queue("a_test_queue", durable: false) EventMachine.run do EM::WebSocket.run(server_config_hash) do |ws| ws.onopen { |handshake| do_something_on_open(ws, handshake) } ws.onmessage { |msg| do_something_else_on_message(ws, msg) } ws.onclose { do_nothing_on_close(ws) } ws.onerror { |error| definitely_do_nothing_on_error(error) } end queue.subscribe(manual_ack: true, block: false) do |delivery_info, properties, body| message = JSON.parse(body) # it's smart and convenient to use JSON do_magic_on(message) channel.ack(delivery_info.delivery_tag) end EventMachine::PeriodicTimer.new(1) do send_server_stats_to_manager_email end end Niewiele kodu, który sporo robi bo Facebook sam się nie uzupełni
  • 21. Tymczasem w aplikacji… class Message def push_to_bunny $rabbit_session.publish_message(self.id) end end Tyle wystarczy, żeby wysłać naszą wiadomość do kolejki. Ruby rulez (-:
  • 22. Tadam! • Działa • Jest prosto • Było szybko • Będzie stabilnie
  • 23. Obserwacje • wyjątki dobrze jest obsługiwać w miejscu, w którym się ich spodziewamy. EM domyślnie je przechwytuje i tyle. • nie należy serializować obiektów i wrzucać ich do kolejek. Ale przecież nikt tego nie robi. Robi?
  • 24. Obserwacje… • Bundler.require jest pożyteczny • Obsługę poszczególnych sub-pętli dobrze wrzucić do dedykowanych klas. Kod staje się podatny na testowanie.