Using unicorn changes all these numbers and I don’t have any experience with unicorn and discourse together. I see there’s a unicorn.sample.conf.rb, but the INSTALL-ubuntu.md doesn’t mention using it. There seems to be some hesitation to using unicorn, but maybe not. I’d love @sam or @codinghorror to talk about the virtue of using thin versus unicorn. Has there been problems running under unicorn? Are there issues running sidekiq under unicorn? From what I understand, unicorn is superior to thin in terms of raw requests per second handling.
@sam is the expert on this but he’s on vacation so I’ll try to answer
It comes down to our message bus feature, which allows us to send updates to the browser dynamically. It uses long polling to do this, which only works with a server that can handle thousands of connections, even if they’re mostly idle.
To do this, we make use of the rack hijack API. However, it doesn’t fully work on all servers right now. In particular, thin is a best in class implementation.
Having said that, I think other servers have caught up and with some work we can support them. In particular the edge Passenger should support it (their initial stab had an error).
The first version of the message bus used web sockets. Unfortunately we had many more issues with it, so in the interest of shipping we reverted to long polling.
As for efficiency, long polling is really not that bad. All those connections are idle most of the time. Additionally, to support web sockets in Rails has many of the same issues with server compatibility that long polling does.
I wouldn’t be against adding them back once the message bus is stable and battle tested, but there’s no major advantage right now.
I guess I’m a little confused. I believe “long polling” refers to a timeout on the client side that does an http get to see what data has changed since the last poll. Is that correct? How does that relate to the thin server? It leaves the connection open between the client and server? How does thin handle that? I thought each thin server could only handle a single connection at a time.
Discourse uses the message_bus gem, it supports both thin async and rack hijack. I turned off hijack by default, cause passenger has a very dangerous implementation at the moment.
Keep in mind, unicorn is a stickler about the version of rack it boots with and will not enable hijack unless it boots with rack 1.5 or above, rails 3.2 is quite conservative about its rack version and is locked on 1.4.x
So, bottom line, when we upgrade to Rails 4 we may be able to recommend unicorn. I hate recommending a server that only gives you a subset of the Discourse experience. At the moment I can easily recommend Thin or Puma (with puma you will need to enable long polling)
It sounds like you’re thinking of short polling. Short polling is where you
make a request every x seconds for an update. Long polling involves making
a connection to the server that is held in a pending state. It sits there
doing nothing until the server has something to reply with. When the server
has a message to send to the client, it sends it down the connection, and
then it is closed. The client then immediately opens a new connection to
wait for another message.
Thin can only handle one rails request at a time per process, but the many
connections in a pending state dont count, since they’re sitting there
doing nothing until they need a message.
We prefer Unicorn cause it has served us well, has been mega stable and poses no particular problems at the moment.
Technically you could use Puma in a memory starved environment in a single process mode, but loss of isolation may end up being a big issue, this would be an experiment you would have to run for multiple weeks and report back on gains / losses and any stability issues.