All things Rack, in Amsterdam
This month's meetup from the Amsterdam Ruby group was wholly Rack themed. WeTransfer's Wander Hillen talked about leveraging Ruby processes, and Red Hat's Dávid Halász about smuggling TCP traffic through an HTTP connection.
Serving 10k connections from a single process
The Rack interface that most Ruby webservers expose to applications was designed for the short HTTP request/response cycle. Wander comes from a language with more verbosity, which explains why Rack server provisioning (in little more than a one-liner) blew his mind.
For the meetup Wander repeated an experiment he ran recently, where he tried and leveraged the internals of Rack and Ruby, in order to get more out of a system than you ‘should’ be able to get.
The primary level of provisioning of a server is rather basic, and further tuning is only slightly more difficult. With websockets and Server Sent Events, connections stay open for much longer. In his talk, Wander explored the ‘socket hijack’ technique and tried to squeeze as many connections from a single Puma process as possible (in the context of the meetup): a grand total of 10222. In a blog post published prior to the meetup he managed to register even more connections (65k) from a single instance.
Hongli (Passenger's maintainer) talking to Wander (with laptop) and other meetup attendees
Smuggling TCP traffic through an HTTP connection
In order to check if a socket is ready to read and write, Dávid would typically use IO.select
. But the IO.select
package doesn't handle dependencies well. And the alternatives (EventMachine, Celluloid, Async, ... or refraining from Ruby altogether 😱) are mostly incompatible with the Postgres configuration ManageIQ (the project Dávid is working on) uses.
Dávid briefly looked into EPOLL (which doesn't support BSD or MacOS), and created a generic purrpose (the extra 'r' is deliberate) TCP-to-TCP proxy for Ruby implemented using epoll. The SurroGate gem is open source.
Dávid then decided to attempt 'smuggling' traffic, and wrote his own TCP-over-HTTP solution Purr. Purr makes it possible to smuggle any kind of TCP traffic (SSH, VNC, etc.) through an HTTP connection. A Rack-based web server implemented in Ruby, Purr sports a desktop client application written in Go (Dávid's very first go at... Go). Purr is also in no way production ready.
Proud Purr maintainer Dávid Halász
Isn't Passenger also Rack?
Ruby on Rails promotes Puma as the default Rack server. We'd of course love for you to give Passenger a try. Let us know what you think!