

Nginx module to turn it into a long-polling message queuing HTTP push server. - labria
http://github.com/slact/nginx_http_push_module

======
sh1mmer
This just creepy. We had a session at the Real-time web summit yesterday where
we described needing something like this.

One of the guys from Google named it the "Comet Tornado Reverse HTTP Proxy"
because we were talking about adapting Tornado, this look like exactly that.

------
slact
hey guys, I'm responsible for this frankenstein of a creation. I am 2 bugs
away from a release with quite a few essential improvements.

(of course, the bugs in question seem to be concurrency related, so it might
take a day or two or more to fix)

Clever suggestions and constructive forks are welcome.

------
karanbhangui
I'm curious how this compares to twisted.web/tornado in terms of use case
(friendfeed type sites). Can anyone quickly explain this to me? Thanks!

~~~
labria
Tornado is a web framework on its own, it handles the polling and the replies
internally. This nginx module is just a helper to the framework behind it. It
keeps the connections to the listeners, waiting for the framework to signal
it, and then sends the message back to the listeners.

------
simonw
Quick question for any nginx experts: the following config setting:

set $push_channel_id $arg_id; #/?id=239aff3 or somesuch

Means that the ?id= querystring paramater is used as the push channel ID. Any
idea if it would be possible to set it up so /channel/12345/ would result in
12345 being set as the push channel ID?

~~~
wizard_2
Quite possible - You'd need to use the rewrite module to pass it as an
argument. <http://wiki.nginx.org/NginxHttpRewriteModule>

Maybe something like this...

    
    
      location / {
        rewrite  ^/channel/(.+)$ /channel/?id=$1 last;
      }
      
      location /channel/{
        #stuff
        set $push_channel_id $arg_id; #/?id=239aff3 or somesuch
      }

------
jbyers
Nice. I hacked something like this into nginx a while back via kestrel but a
native module is better by far. Assuming it's up to the high expectations of
nginx stability, it's going to further cement nginx as the proxy / lightweight
webserver of choice.

~~~
bham
Do you work at Twitter? I wasn't aware that anyone was using Kestrel outside
of Twitter - Zing!

------
WALoeIII
This is fantastic. EZ-Mode push using a very simple to deploy piece of
software.

------
mrshoe
If I'm reading the docs correctly, you'd have to make a server-side HTTP
request from your synchronous app to nginx for each message you want to push
_to each client_. I'm pretty sure that will be prohibitively slow.

It would be much nicer if you could make one server-side request for each
event, and have nginx track which clients are interested in that type of event
and even queue that event for a while for clients that are yet to connect.

~~~
labria
No. You just set the "push_listener_concurrency" setting to "broadcast", and
have as many listeners on one channel as you like.

------
elliottkember
Personally, I prefer Juggernaut (<http://juggernaut.rubyforge.org/>) for this.
Sure, it's Flash, but it just seems like a bit less of a hack than long-
polling.

~~~
Jasber
Have you had any problems using this in production? My understanding with
using Flash/Java is that all traffic has to be tunneled through port 80 to not
interfere with proxy servers. Even then sometimes traffic that doesn't look
like HTTP can be blocked. Has this been a problem for you?

<http://cometdaily.com/2008/09/30/why-flash-must-adopt-comet/>

<http://orbited.org/blog/2007/08/juggernaut-is-a-bad-idea/>

~~~
defied
I'm using it in production since last week, about 50,000 connections / day.
For some reason it seems to stop/crash after 24-36hrs without leaving anything
in the logs.

I am using it on port 443 (https).

------
_ck_
Does Google do something like this for their servers for the chat service
inside gmail?

I've noticed it can keep http connections open for extremely long times.

~~~
axod
<http://en.wikipedia.org/wiki/Comet_(programming)> is a good ref. Gmail chat
does this.

~~~
gcb
This wiki page covers mostly the frontend part.

The link covers a server side message passing interface.

I just glanced over it (do not use nginx) think it's just a more efficient way
for your idle process to know if they need to send anything over the wire or
if they can keep idleing.

~~~
wizard_2
I do use nginx. This uses a "Simplish HTTP Push Relay Protocol". It's a way
for your app (via curl or any other http library) to "connect" to your http
clients.

It has a few interesting options. "messages" are passed by a "channel id" and
you can have any number of long polling listeners on a channel, or you can
error out the first or last connections on a channel so there is only one
listener at a time. If you have multiple listeners the message becomes a
broadcast.

You also have a configurable amount of memory to buffer messages in the event
there is no listener on a channel, or the listener is busy (receiving a
message I guess). You can also set limits on number of messages per channel
and a timeout.

I can see the advantages of this easily. The connections in nginx are much
less resource intensive then a rails or php fast-cgi. You'll end up using much
less ram. I know python has twisted and there are few others webservers for
other languages, but this would allow me to run a php based chat server and
take advantage of long polling.

I like it.

