102
EventMachine Что делать, если вы соскучились по callback-ам? Николай Норкин, 7Pikes

Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

  • Upload
    others

  • View
    13

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EventMachine Что делать, если вы соскучились

по callback-ам?

Николай Норкин, 7Pikes

Page 2: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Что такое асинхронность?

2

Page 3: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Наша жизнь синхронна и однопоточна

3

Page 4: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Наша жизнь синхронна и однопоточна

3

Page 5: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Асинхронность в вычислительной технике

4

Работа Ожидание

Page 6: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Асинхронность в вычислительной технике

4

Работа Ожидание

Page 7: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Reactor

5

Page 8: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Reactor

5

Event Loop

Ожидание событий

Обработка событий

Events Callbacks

Page 9: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EventMachine

6

Page 10: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Когда нам нужен EventMachine?

7

Page 11: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Когда нам нужен EventMachine?

• Работа с сетью (HTTP, TCP, e.t.c)

• Работа с ФС

• Запросы к БД

• любые другие операции, вынуждающие процесс ждать

7

Page 12: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Параллельные запросы

8

Page 13: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Threads

9

threads = []responses = []responses_mutex = Mutex.new

request_count.times do threads << Thread.new(responses) do |responses| response = RestClient.get URL responses_mutex.synchronize { responses << response } endend

threads.each(&:join)

Page 14: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Время

10

02,55

7,510

12,515

17,520

22,525

10 50 100 200 500 1000

Threads

Page 15: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Память

11

0120240360480600720840960

1 0801 200

10 50 100 200 500 1000

Threads

Page 16: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EventMachine

12

responses = []

EventMachine.run do multi = EventMachine::MultiRequest.new

request_count.times { |i| multi.add i, EM::HttpRequest.new(URL).get }

multi.callback do responses = multi.responses[:callback].values.map(&:response) EventMachine.stop endend

Page 17: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Время

13

02,55

7,510

12,515

17,520

22,525

10 50 100 200 500 1000

Threads EventMachine

Page 18: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Память

14

0120240360480600720840960

1 0801 200

10 50 100 200 500 1000

Threads EventMachine

Page 19: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Быстродействие

15

Page 20: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

rack

16

require 'rubygems'require 'rack'

class HelloWorld def call(env) [200, { 'Content-Type' => 'text/plain' }, ["Hi! I'm Rack!"]] endend

Rack::Handler::WEBrick.run HelloWorld.new, Port: 8000

Page 21: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

node

17

var http = require('http');

http.createServer(function(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end("Hi! I'm Node.JS\n");}).listen(8000, '127.0.0.1');

Page 22: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EventMachine

18

require 'rubygems'require 'eventmachine'

class RequestHandler < EM::Connection def receive_data(_) data = "Hi! I'm EventMachine!" send_data("HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n#{data}\n") close_connection_after_writing endend

EM.run do EM.start_server('127.0.0.1', 8000, RequestHandler)end

Page 23: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

19

2000

4000

6000

8000

10000

5 618,563 658,25

396,99

rack node EM

Запросов в секунду

Page 24: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

19

2000

4000

6000

8000

10000

5 618,563 658,25

396,99

rack node EM

Запросов в секунду

Page 25: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

19

2000

4000

6000

8000

10000

5 618,563 658,25

396,99

rack node EM

Запросов в секунду

Page 26: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

19

2000

4000

6000

8000

10000

5 618,563 658,25

396,99

rack node EM

Запросов в секунду

Page 27: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Установка

20

gem install eventmachine

require "eventmachine"

EventMachine == EM

Page 28: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EventMachine API

21

Page 29: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.run• Запускает EventLoop

• Принимает блок

• Запускается в текущем потоке

EM.run do puts "Will be executed"endputs "Will be never reached"

22

Page 30: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.stop

EM.run do puts "Will be executed" if EM.reactor_running? puts "Yeap. I'm running right now" end EM.stopendputs "Hoorayyy! I've been called too!"

23

Page 31: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

24

Threads

Page 32: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

24

Threadsthread = Thread.currentThread.new do EM.run do thread.wakeup # do whatever you want endend

Thread.stop

Page 33: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

24

Threadsthread = Thread.currentThread.new do EM.run do thread.wakeup # do whatever you want endend

Thread.stop

• Не блокирует основной поток• Печальная ситуация с тредами в ruby• Появляются проблемы с thread-safety

Page 34: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.schedule

25

• Нужно использовать, если тред EM отличен от основного треда

• Бережет от threaded-проблем

• Обертка вокруг EM.next_tick

Page 35: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.next_tick

26

Ставит блок на следующую итерацию реактора

Page 36: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.next_tick

26

Ставит блок на следующую итерацию реактора

1000.times do long_processingend

Page 37: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.next_tick

26

Ставит блок на следующую итерацию реактора

1000.times do long_processingend

n = 0iter = proc do if n < 1000 long_processing n += 1 EM.next_tick(&iter) endendEM.next_tick(&iter)

Page 38: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Таймеры

27

Page 39: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

28

EM.run do puts "It's time to take a nap" sleep(60*60*24*7) puts "Gosh... How long have I been sleeping?" EM.stopend

Page 40: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

28

EM.run do puts "It's time to take a nap" sleep(60*60*24*7) puts "Gosh... How long have I been sleeping?" EM.stopend

Page 41: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

29

EM::Timer.new(60*60*24*7) do puts "See ya one week later"end

Page 42: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

29

EM::Timer.new(60*60*24*7) do puts "See ya one week later"end

timer = EM::PeriodicTimer.new(1) do puts "Second passed"end

Page 43: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

29

EM::Timer.new(60*60*24*7) do puts "See ya one week later"end

timer = EM::PeriodicTimer.new(1) do puts "Second passed"endputs "...or not" if timer.cancel

Page 44: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.defer

30

Запускает блок параллельно основному потоку

Page 45: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM.defer

30

EM.defer( proc { long_operation }, proc { |result| process(result) })

Запускает блок параллельно основному потоку

В отдельном потоке

В основном потоке

Page 46: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM::Deferrable

31

Page 47: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM::Deferrable

• Это не defer

• Модуль

• Добавляется к вашим классам

• Коллбэки

31

Page 48: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

32

class DeepThought include EM::Deferrable

attr_reader :answer

def search puts 'Looking up for a meaning of life' EM.add_timer(60*60*24*365*7_500_000) do @answer = 42 succeed(@answer) end rescue raise 'Oops... Something wrong' endend

greatest_computer = DeepThought.newgreatest_computer.callback do |answer| puts 'Answer to the Ultimate Question' \ ' of Life, the Universe,' \ " and Everything is #{answer}"endgreatest_computer.errback do |error| puts "Oops... #{error}"endgreatest_computer.search

Page 49: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

32

class DeepThought include EM::Deferrable

attr_reader :answer

def search puts 'Looking up for a meaning of life' EM.add_timer(60*60*24*365*7_500_000) do @answer = 42 succeed(@answer) end rescue raise 'Oops... Something wrong' endend

greatest_computer = DeepThought.newgreatest_computer.callback do |answer| puts 'Answer to the Ultimate Question' \ ' of Life, the Universe,' \ " and Everything is #{answer}"endgreatest_computer.errback do |error| puts "Oops... #{error}"endgreatest_computer.search

Функциональность Deferrable

Page 50: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

32

class DeepThought include EM::Deferrable

attr_reader :answer

def search puts 'Looking up for a meaning of life' EM.add_timer(60*60*24*365*7_500_000) do @answer = 42 succeed(@answer) end rescue raise 'Oops... Something wrong' endend

greatest_computer = DeepThought.newgreatest_computer.callback do |answer| puts 'Answer to the Ultimate Question' \ ' of Life, the Universe,' \ " and Everything is #{answer}"endgreatest_computer.errback do |error| puts "Oops... #{error}"endgreatest_computer.search

Успешное завершение

Функциональность Deferrable

Page 51: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

32

class DeepThought include EM::Deferrable

attr_reader :answer

def search puts 'Looking up for a meaning of life' EM.add_timer(60*60*24*365*7_500_000) do @answer = 42 succeed(@answer) end rescue raise 'Oops... Something wrong' endend

greatest_computer = DeepThought.newgreatest_computer.callback do |answer| puts 'Answer to the Ultimate Question' \ ' of Life, the Universe,' \ " and Everything is #{answer}"endgreatest_computer.errback do |error| puts "Oops... #{error}"endgreatest_computer.search

Успешное завершение

Ошибка

Функциональность Deferrable

Page 52: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM::Channel

33

channel = EM::Channel.newsid = channel.subscribe do |msg| puts "Got #{msg}»endchannel.push("message")channel.unsubscribe(sid)

Удобный thread-safe способ обмена данными внутри приложения

Page 53: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Работа с сетью

34

• EM.start_server (stop_server) • EM.connect

server_signature = EM.start_server("0.0.0.0", 8080, ClientConnection)EM.stop_server(server_signature)

EM.connect("/sockets/mysql.sock", MySqlConnection)

Page 54: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Работа с сетью

34

• EM.start_server (stop_server) • EM.connect

server_signature = EM.start_server("0.0.0.0", 8080, ClientConnection)EM.stop_server(server_signature)

EM.connect("/sockets/mysql.sock", MySqlConnection)

Наследует от EM::Connection

Page 55: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM::Connection

35

• post_init • connection_completed • receive_data • unbind • ssl_verify_peer • ssl_handshake_completed

События (вызывает EventMachine)

Методы (вызывает пользователь)

• send_data • close_connection • close_connection_after_writing • get_peername • pause/resume • e.t.c

Page 56: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

EM::Protocolsaka EM::P

Page 57: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Традиционный способ получения данных

37

Page 58: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Традиционный способ получения данных

37

send_data("Rudy")send_data("A message to you Rudy")

receive_data(«Rudy\n")receive_data("A messa")receive_data("ge to you Rudy\n")

Сеть

Page 59: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

С использование EM::Protocols

38

class Client < EM::Connection include EM::P::LineText2

def receive_line(text) puts text endend

Page 60: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

С использование EM::Protocols

38

class Client < EM::Connection include EM::P::LineText2

def receive_line(text) puts text endend

Page 61: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

39

class Client < EM::Connection include EM::P::ObjectProtocol

def receive_object(object) puts "Finally received an amazing #{object.class}" send_object(thank: "you!") endend

Выведет «Finally received an amazing Hash»

EM::P::ObjectProtocol

Page 62: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Другие протоколы

• HttpClient and HttpClient2

• Stomp

• Memcache

• SmtpClient and SmtpServer

• SASLauth and SASLauthclient

40

• LineProtocol, LineAndTextProtocol and LineText2

• HeaderAndContentProtocol

• Postgres3

• ObjectProtocol

+ Можно писать свои и есть куча сторонних

Page 63: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Пример

41

module EventMachine module Protocols module ApostoreMessage def receive_data(data) (@buf ||= '') << data while @buf.slice!(/#{Apostore::Config.message_beggining}(?<msg>.*?)#{Apostore::Config.message_ending}/) message = Regexp.last_match[:msg] next if message.nil? parsed_message = Apostore::Message.new(message) receive_message(parsed_message) end end

def receive_message(_message) # stub end end endend

Page 64: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

C10K

42

Page 65: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

43

• select и poll медленныe. Они вынужденны передавать все дескрипторы и возвращать состояние для всех

• Аналогично не только для файлов, но и для соединений и т.п.

• epoll/kqueue срабатывает при готовности дескриптора

• EM по умолчанию работает с select

select/poll и epoll

Page 66: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Как включить epoll?

44

EM.epoll

Page 67: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Как включить epoll?

44

EM.epoll

Page 68: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

45

Другие фичи• system - системные вызовы

• watch - мониторинг дескриптора

• attach - подключение объектов ввода-вывода

• watch_file - мониторинг файлов

• watch_process - мониторинг процессов

• popen - работа с внешними процессами

e.t.c

Page 69: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки

46

Page 70: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

46

Page 71: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

47

question = some_operationresponse = get_http(question)answer = build_answer(response)send_answer(answer)log("done")

Page 72: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

47

question = some_operationresponse = get_http(question)answer = build_answer(response)send_answer(answer)log("done")

some_operation do |question| get_http(question) do |response| build_answer(response) do |answer| send_answer(answer) do log("done") end end endend

Page 73: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

• thread-safety

48

Page 74: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

49

x = 0

10.times.map do |i| EM.defer do puts "before (#{ i }): #{ x }" x += 1 puts "after (#{ i }): #{ x }" endend

before (0): 0after (0): 1before (2): 1before (4): 1after (4): 3before (7): 1after (7): 4after (2): 2before (5): 1after (5): 5before (9): 1before (3): 1before (6): 1after (6): 8after (3): 7before (8): 1after (8): 9after (9): 6before (1): 1

Page 75: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

50

x, mutex = 0, Mutex.new

10.times.map do |i| EM.defer do mutex.synchronize do puts "before (#{ i }): #{ x }" x += 1 puts "after (#{ i }): #{ x }" end endend

before (0): 0after (0): 1before (1): 1after (1): 2before (2): 2after (2): 3before (3): 3after (3): 4before (4): 4after (4): 5before (5): 5after (5): 6before (6): 6after (6): 7before (7): 7after (7): 8before (8): 8after (8): 9before (9): 9after (9): 10

Page 76: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

• thread-safety

• Утечки и разбухание памяти

51

Page 77: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

52

PHP• По процессу на запрос • Память вычищается после каждого запроса

EM• Все выполняется в одном процессе

• Следить за памятью нужно самому

Page 78: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

class Connection < EM::Connection @@connections = []

def post_init @@connections << self endend

53

Page 79: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

class Connection < EM::Connection @@connections = []

def post_init @@connections << self endend

53

Page 80: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

class Connection < EM::Connection @@connections = []

def post_init @@connections << self endend

53

Page 81: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

class Connection < EM::Connection @@connections = []

def post_init @@connections << self endend

53

Page 82: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

54

Process 'robot' status running monitoring status monitored pid 2153 parent pid 1 uptime 105d 5h 50m children 0 memory kilobytes 33352 memory kilobytes total 33352 memory percent 0.8% memory percent total 0.8% cpu percent 0.0% cpu percent total 0.0%

Real-life

Page 83: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

• thread-safety

• Утечки и разбухание памяти

• Блокирование неблокирующего ввода-вывода

55

Page 84: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

56

require 'eventmachine'

EM.run do start_time = Time.now

EM.next_tick do puts Time.now - start_time sleep(2) end

EM::Timer.new(1) do puts Time.now - start_time EM.stop end

sleep(2)end

Page 85: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

56

require 'eventmachine'

EM.run do start_time = Time.now

EM.next_tick do puts Time.now - start_time sleep(2) end

EM::Timer.new(1) do puts Time.now - start_time EM.stop end

sleep(2)end

2.0042184.004673

Page 86: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

• thread-safety

• Утечки и разбухание памяти

• Блокирование неблокируемого ввода-вывода

• MRI, GIL

57

Page 87: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 88: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 89: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 90: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 91: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 92: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 93: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

58

Concurency vs Parallelism

Page 94: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

59

Concurency vs Parallelism• MRI • Rubinius 1 • MagLev

• Rubinius 2 • JRuby • MacRuby

Page 95: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Недостатки• Колбэки

• thread-safety

• Утечки и разбухание памяти

• Блокирование неблокируемого ввода-вывода

• MRI, GIL

• Бедноватая документашка

60

Page 96: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Инструменты на основе EventMachine

• Thin

• Goliath

• amqp

• logstash

• websocket-rails

61

Page 97: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Библиотеки• https://github.com/igrigorik/async-rails

• https://github.com/kyledrake/sinatra-synchrony

• https://github.com/stevegraham/em-rspec

• https://github.com/jcoglan/rspec-eventmachine

• https://github.com/igrigorik/em-synchrony

62

Page 98: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

em-synchrony• Делает EM «синхронным»

• Основан на Fiber

• Содержит много синхронизированных частей EventMachine

• Возможность синхронизировать любую асинхронную функцию

63

Page 99: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Как работает?

64

def http_get(url) f = Fiber.current http = EventMachine::HttpRequest.new(url).get http.callback { f.resume(http) } return Fiber.yieldend

EventMachine.run do Fiber.new{ page = http_get('http://www.google.com/') puts "Fetched page: #{page.response_header.status}" }.resumeend

Page 100: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Выводы

• EventMachine добавляет скорости

• EventMachine добавляет проблем

65

Page 101: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Куда дальше?• Homepage http://rubyeventmachine.com/

• GitHub https://github.com/eventmachine/eventmachine

• Wiki https://github.com/eventmachine/eventmachine/wiki

66

Page 102: Николай Норкин, 7PikesКогда нам нужен EventMachine? • Работа с сетью (HTTP, TCP, e.t.c) • Работа с ФС • Запросы к БД

Вопросы?

67

[email protected]

https://github.com/duderman