Skip to content

Instantly share code, notes, and snippets.

@WJWH
Created October 15, 2018 09:12
Show Gist options
  • Save WJWH/f10b3386e15023e72ac136a7ab060dc9 to your computer and use it in GitHub Desktop.
Save WJWH/f10b3386e15023e72ac136a7ab060dc9 to your computer and use it in GitHub Desktop.
The double hijack trick, serving 65k connections from a single ruby process
# This server demo does a socket hijack in Rack and then saves the socket to a global variable
# to prevent it from being GCed when the Puma thread ends. It will then write "BEEP" to each
# socket every ten seconds to prevent the connection timing out. During testing, it easily
# handled up to 65523 connections, after which it ran into the `ulimit` for open file descriptors.
# The bit with the waiting area is there because a normal `Set` is not thread safe and it would
# drop socket due to race conditions. The `Queue` is thread safe and will make sure all sockets
# are preserved.
# run with `rackup -q -p 8000 -o 0.0.0.0 c10k.ru`
# testing: install `ab` and then run `ab -c 20000 -n 20000 <ip adress of server>:8000/
# Make sure you have puma and rack installed globally, as there is no gemfile for this demo.
require 'puma'
require 'rack'
require 'set'
conn_waiting_area = Queue.new
conn_storage = Set.new
# "Reactor"
Thread.new do
loop do
begin
sleep 3
until conn_waiting_area.empty?
conn = conn_waiting_area.deq
conn_storage << conn
end
start_time = Time.now
conn_storage.each do |c|
begin
c << "BEEP\n"
rescue
conn_storage.delete(c)
end
end
end_time = Time.now
puts "Number of clients connected: #{conn_storage.length}, time for entire write run: #{end_time - start_time}"
rescue StandardError => e
p e
end # begin
end # loop
end # Thread new
app = lambda do |env|
response_headers = {}
response_headers['Transfer-Encoding'] = 'binary'
response_headers["Content-Type"] = "text/plain"
response_headers["rack.hijack"] = lambda do |io|
conn_waiting_area << io
end
[200, response_headers, nil]
end
run app
@chase439
Copy link

chase439 commented Nov 1, 2018

Very nice explanation of Rack and how to hijack it!

@david-pm
Copy link

david-pm commented Nov 2, 2018

😍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment