Event Driven Architecture
Understanding Event Loops and the point of async
Loïc Faugeron
http://constant.co
@epiloic
Slide 2
Slide 2 text
Robert C. Martin - https://blog.8thlight.com/uncle-bob/2015/08/06/let-the-magic-die.html
“If you’ve ever written a
web server, then the magic
is gone”
@epiloic
Slide 3
Slide 3 text
1. HTTP Server
2. Event Loop
3. Scheduling
4. Promise
5. Thread Pool
Slide 4
Slide 4 text
1. A story of Input / Output
Also known as “I/O”
Slide 5
Slide 5 text
What is “I/O”?
Server / Client communication via
sockets
5 @epiloic
Slide 6
Slide 6 text
Example: HTTP Server
6 @epiloic
Slide 7
Slide 7 text
Creating a socket
7 @epiloic
Slide 8
Slide 8 text
8 @epiloic
Caution!
When the queue
is full...
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 9
Slide 9 text
Looping to infinite and beyond
9 @epiloic
Slide 10
Slide 10 text
Creating dedicated sockets for clients
10 @epiloic
Slide 11
Slide 11 text
11 @epiloic
Unqueueing
To avoid...
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 12
Slide 12 text
Waiting for data to be received…
12 @epiloic
Slide 13
Slide 13 text
I/O is slow
Think about latency
See https://gist.github.com/jboner/2841832#file-latency-txt
Slide 14
Slide 14 text
14 @epiloic
Meanwhile
More queueing
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 15
Slide 15 text
HTTP application
15 @epiloic
Slide 16
Slide 16 text
Waiting for data to be sent…
16 @epiloic
Slide 17
Slide 17 text
I/O is really slow
And unreliable
See https://gist.github.com/jboner/2841832#file-latency-txt
Slide 18
Slide 18 text
18 @epiloic
Meantime
More queueing
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 19
Slide 19 text
Saying goodbye to the client
19 @epiloic
Slide 20
Slide 20 text
Queue System
Handles ~100 clients
Picture: lorenz.markus97 (CC BY 2.0 - https://flic.kr/p/szWiqL)
Slide 21
Slide 21 text
Handling 10 000 clients?
If only we could do something else
while waiting...
21 @epiloic
See the C10K problem: http://www.kegel.com/c10k.html by Dan Kegel
Slide 22
Slide 22 text
2. Hang on!
ready = poll(to_watch)
Did you see what I did there?
Slide 23
Slide 23 text
Many implementations
select, poll, epoll, kqueue, IOCP
23 @epiloic
See epoll VS kqueue: http://www.eecs.berkeley.edu/~sangjin/2012/12/21/epoll-vs-kqueue.html by Sangjin Han
Slide 24
Slide 24 text
Example: HTTP Server
24 @epiloic
Slide 25
Slide 25 text
Collecting sockets to watch
25 @epiloic
Slide 26
Slide 26 text
Waiting for sockets to be ready
26 @epiloic
Slide 27
Slide 27 text
HTTP server socket is ready
27 @epiloic
Slide 28
Slide 28 text
Collecting more sockets to watch
28 @epiloic
Slide 29
Slide 29 text
HTTP client socket is ready
29 @epiloic
Slide 30
Slide 30 text
No longer watching closed sockets
30 @epiloic
Slide 31
Slide 31 text
Receiving events in a loop
That’s an Event Loop!
31 @epiloic
Slide 32
Slide 32 text
Refactoring Event Loop
32 @epiloic
Slide 33
Slide 33 text
No distinctions between sockets
33 @epiloic
Slide 34
Slide 34 text
Injecting Event Loop in callbacks
34 @epiloic
Slide 35
Slide 35 text
Allows decoupled code
Put Server / Client logic in callbacks
35 @epiloic
Slide 36
Slide 36 text
Event Loop usage
36 @epiloic
Slide 37
Slide 37 text
Adding server socket to Event Loop
37 @epiloic
Slide 38
Slide 38 text
Handling new client connections
38 @epiloic
Slide 39
Slide 39 text
Handling received data
39 @epiloic
Slide 40
Slide 40 text
Efficient Queue
Using blocking time
Picture: Sean McEntee (CC BY 2.0 - https://flic.kr/p/a7zKqg)
Slide 41
Slide 41 text
“Blocking,
If it’s not solving all your problems,
You simply aren’t using enough of it.”
41 @epiloic
Slide 42
Slide 42 text
Handling 0 clients?
If only we could do something else
while waiting...
42 @epiloic
Slide 43
Slide 43 text
3. Wait a second!
poll(to_watch, timeout)
Did you see what I did there?
Slide 44
Slide 44 text
Schedulers
One off, periodic, idle, etc...
44 @epiloic
Slide 45
Slide 45 text
Example: One off Scheduler
45 @epiloic
Slide 46
Slide 46 text
Adding timer callbacks
46 @epiloic
Slide 47
Slide 47 text
Checking if any timers are due
47 @epiloic
Slide 48
Slide 48 text
Calling due timers’ callbacks
48 @epiloic
Slide 49
Slide 49 text
Removing one off timers afterwards
49 @epiloic
Slide 50
Slide 50 text
Scheduled Event Loop
50 @epiloic
Slide 51
Slide 51 text
Setting a smart timeout
51 @epiloic
Slide 52
Slide 52 text
Ticking the clock
52 @epiloic
Slide 53
Slide 53 text
Efficient Queue
Using waiting time
Picture: fdecomite (CC BY 2.0 - https://flic.kr/p/BW7Hh)
Slide 54
Slide 54 text
“Waiting,
If it’s not solving all your problems,
You simply aren’t using enough of it.”
54 @epiloic
Slide 55
Slide 55 text
Nesting more callbacks?
If only we could make async code feel
more sync...
55 @epiloic
Slide 56
Slide 56 text
4. Async what you did
there...
No more puns, I promise
Slide 57
Slide 57 text
Futures and promises
Async functions return a value,
register callbacks via this value
57 @epiloic
Slide 58
Slide 58 text
Example: Deferrer / Promise
58 @epiloic
Slide 59
Slide 59 text
Injecting Deferrer’s setter in Promise
59 @epiloic
Slide 60
Slide 60 text
Passing callback to Promise...
60 @epiloic
Slide 61
Slide 61 text
… Which sets it in the Deferrer
61 @epiloic
Slide 62
Slide 62 text
Resolving the Deferrer, calls
callbacks
62 @epiloic
Slide 63
Slide 63 text
Chaining calls
To make it feel sync
Picture: Mark Skipper (CC BY 2.0 - https://flic.kr/p/4FQ8DU)
Slide 64
Slide 64 text
“Callback,
If it’s not solving all your problems,
You simply aren’t using enough of it.”
64 @epiloic
Slide 65
Slide 65 text
Usage example?
If only we could have a usage
example...
65 @epiloic
Slide 66
Slide 66 text
5. Filesystem U/O
More U/O (Uh Oh) than I/O
Slide 67
Slide 67 text
Slowest I/O?
Filesystem
See https://gist.github.com/jboner/2841832#file-latency-txt
Slide 68
Slide 68 text
Poor non-blocking support
Cannot be used with poll()
68 @epiloic
See asynchronous disk I/O: http://blog.libtorrent.org/2012/10/asynchronous-disk-io/ by Arvid Norberg
Slide 69
Slide 69 text
Solution?
Use the force a Thread Pool
69 @epiloic
Slide 70
Slide 70 text
Non Blocking Filesystem
70 @epiloic
Slide 71
Slide 71 text
Deferring FS call to Thread Pool
71 @epiloic
Slide 72
Slide 72 text
Calling callbacks, once thread is done
72 @epiloic
Slide 73
Slide 73 text
Blocking I/O
Wrapped, in Threads
Picture: Jamie (CC BY 2.0 - https://flic.kr/p/9Av7cj)
Slide 74
Slide 74 text
“Threading,
If it’s not solving all your problems,
You simply aren’t using enough of it.”
74 @epiloic
Slide 75
Slide 75 text
“Threading,
If it’s not solving all your problems,
You simply aren’t using enough of it.”
75 @epiloic
NOT!
Limits are good
Slide 76
Slide 76 text
76 @epiloic
Infinite pool
Error cause:
Filesystem limit
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 77
Slide 77 text
77 @epiloic
Infinite limit
Error cause:
HDD/SSD burned
Picture: Nick Webb (CC BY 2.0 - https://flic.kr/p/5AykUp)
Slide 78
Slide 78 text
True story
Usually pool of 4 threads
78 @epiloic
See ReactPHP filesystem - a word of caution:
https://blog.wyrihaximus.net/2015/03/reactphp-filesystem/#a-word-of-caution by Cees-Jan Kiewiet
Slide 79
Slide 79 text
ConclusI/On
Slide 80
Slide 80 text
Making use of waiting time,
to handle more clients
80 @epiloic
Non blocking Idle Sync Feeling Blocking
Event Loop Scheduling Promise Thread Pool
Slide 81
Slide 81 text
81 @epiloic
Used by...
nginx
See how it outperforms Apache: https://www.nginx.com/blog/nginx-vs-apache-our-view/
Picture: Thijs Feryn (https://speakerdeck.com/thijsferyn/varnish-or-nginx-symfony-live)
Slide 82
Slide 82 text
82 @epiloic
Used by...
Libuv (Node.js)
Node.js is a trademark of Joyent, Inc. and is used with its permission. We are not endorsed by or affiliated with Joyent.
See an Introduction to libuv: https://nikhilm.github.io/uvbook/introduction.html by Nikhil Marathe
Slide 83
Slide 83 text
83 @epiloic
Used by…
You?
Slide 84
Slide 84 text
Thank you
84 @epiloic
Transcript of this presentation, in a blog article: https://gnugat.github.io/2016/04/27/event-driven-architecture.html