第1页
Async Server And Fiber
c_zlui@groupon.com
第2页
Me
github/luikore ruby-china/luikore
第3页
Motivation
第4页
Challenges To Ruby
第5页
Ruby Advantages
Unicode done right
"".length
Builtin continuation - Fiber And...
第6页
Fast
第7页
How To Build A High Performance Server
第8页
How To Build An Async Server
第9页
How To Build An Async Server Yet Providing Good API
第10页
Study The Background
第12页
The Bottle Neck
Client Side Of View
IO bound - network is slow CPU bound - complex page rendering Server load - wait for other requests to finish
第13页
The Bottle Neck
Server Side Of View
IO bound - visiting database / oauth is slow CPU bound - context switch
第14页
Scaling
Increase App Throughput
Reduce server side IO-waiting is the most effective way Create less threads, to avoid context switching
第15页
Learn From Existing Solutions
第16页
Chances To Ruby
第17页
Limited Server Objects
第18页
Many Crazy Clients
第19页
Multiplexing
第20页
Single Threaded
One Client, One Process, Prefork
unicorn -- multiplex with accept thin -- multiplex with load balancer
第21页
Multithreaded
One Client, One Thread, No Prefork
puma, recommended for rails4 A simple way to implement is to use POSIX functions with callbacks: aio_read(), aio_write()
第22页
Single Threaded And Event Loop
One Client, One Event Context, Prefork
nginx, redis, nodejs, twisted, eventmachine
第23页
Thread Pool On Event Loop
One Client, One Event Context, No Prefork
erlang, golang, scala actors
第24页
Hello World
第25页
TCPSocket In 5 Minutes
client
TCPSocket.new host, port
server
TCPServer.new host, port
receive
socket.read socket.read_nonblock
send
socket.write socket.write_nonblock
第26页
Hello World HTTP Server
server = TCPServer.new 'localhost', 4000 loop do
c = server.accept c << "HTTP/1.1 200 OK Content-Length: 12
Hello world!" c.close
end
第27页
Make It Fast
第28页
NonBlocking Our Loop
loop do client = server.accept Thread.new do ... end
end
第29页
Threads Are Outdated
Lets Use System Events
第30页
Multiplexing Functions
select
IO.select r, w, err, timeout
poll IO.poll fds, timeout
第31页
System Events
Linux For Example
poll - iterate check all fds epoll - is more effective and provides more options
第32页
Epoll In 5 Minutes
sudo apt-get install manpages-dev man epoll
第33页
Epoll In 5 Minutes
register event: epoll_ctl()
retrieve event: epoll()
第34页
Cons
Ruby does not ship with epoll API. You need to wrap it with C-ext.
第35页
Loop With Epoll
loop do event = epoll(timeout) if from_server?(event) connection = server.accept else connection = find_conn_by(event) end ... # resume processing
end
第36页
How To Make It Resumable?
第37页
Eventmachine
async web server
第38页
clients are multiplexed to EM::Connection
you define callbacks for readable events: def receive_data(data)
第39页
"Resume Processing"
connection.receive_data read_nonblock
第40页
Make It Good
第41页
How EM Send_data Works
write to socket, if the socket can’t take any more, append the rest to a buffer chain when the socket becomes writable again (IO event), try consume the buffer chain
第42页
Pitfalls
Callbacks Are Not Sufficient
avoid loss of chained buffers
close_connection_after_writing avoid infinite recursion when registering events in callback:
EM.next_tick{ ... }
第43页
Resume Processing With Fiber
Fiber was the “Thread” in 1.8 Like thread, but lighter, pausable, and no need to lock
第44页
Example
fiber = Fiber.new do i=0 loop do Fiber.yield i += 1 end
end fiber.resume #=> 1 fiber.resume #=> 2
第45页
Read With Fiber
def read_with_fiber result = '' while buffer = read_nonblock result << buffer if nothing to read Fiber.yield :reading! end end result
end
第46页
Write With Fiber
def write_with_fiber content loop do write_nonblock content content = unwritten part of content break if content.empty? Fiber.yield :writing! end
end
第47页
Recall Our Loop
loop do event = epoll(timeout) if from_server?(event) connection = server.accept else connection = find_conn_by(event) end ... # resume processing
end
第48页
loop do event = epoll(timeout) if from_server?(event) connection = server.accept fiber = Fiber.new { ... read_with_fiber ... write_with_fiber } else fiber = find_fiber_by(event) end fiber.resume
end
第49页
Summary
第50页
Network latency and C10k leads to async solutions. With Fiber it can be callback-free.
第51页
In concept it is simple. In practice it is complex: protocols, IO exceptions, ...
第52页
Product
github.com/luikore/nyara faster than sinatra/expressjs in hello world benchmarks