What's the unicorn for Node? How should I think of deployment?

1,263 views
Skip to first unread message

Eric Mill

unread,
Nov 14, 2013, 11:22:16 AM11/14/13
to nod...@googlegroups.com
I'm totally fine being told that the Unicorn model is the wrong way to think of things in Node. But what are the best practices for deploying a Node app where I'd like to be able to scale the number of processes up and down easily on a box? The model I'm used to is putting nginx in front, having it proxy to a Unix socket, and then having Unicorn watch the same Unix socket.

I'm aware of node-http-proxy - should I run one of these with forever -- and then also manage my express processes with forever? How should I be conceiving of the problem?

-- Eric

--

Sam Roberts

unread,
Nov 14, 2013, 1:24:53 PM11/14/13
to nod...@googlegroups.com
On Thu, Nov 14, 2013 at 8:22 AM, Eric Mill <er...@konklone.com> wrote:
> But what are the best practices for deploying a Node app
> where I'd like to be able to scale the number of processes up and down
> easily on a box?

There are probably as many ways to deploy as there are node developers!

You could try out strong-cluster-control. It allows running your app
as single-instance, or as a node cluster, doing run-time scaling using
command line, restarting, etc. It also, soon (running on our staging),
will allow run-time control through strongops, our monitoring and
control.

It's under active development to support our operations, and LoopBack
(our mobile back-end framework), but its a standalone module.

http://docs.strongloop.com/strongnode/
http://docs.strongloop.com/strongnode/#running-applications-with-cluster
https://github.com/strongloop/strong-cluster-control
http://docs.strongloop.com/loopback/


If you do use it (or even don't use it), I'd be interested in feedback.

Cheers,
Sam

Alex Kocharin

unread,
Nov 15, 2013, 4:19:25 AM11/15/13
to nod...@googlegroups.com

On Thursday, November 14, 2013 8:22:16 PM UTC+4, Eric Mill wrote:
I'm totally fine being told that the Unicorn model is the wrong way to think of things in Node. But what are the best practices

There is no such thing called "best practice". You can ask what other people do, but the best way to do something simply doesn't exist.
 
for deploying a Node app where I'd like to be able to scale the number of processes up and down easily on a box? The model I'm used to is putting nginx in front, having it proxy to a Unix socket, and then having Unicorn watch the same Unix socket.

I'm aware of node-http-proxy - should I run one of these with forever -- and then also manage my express processes with forever? How should I be conceiving of the problem?

I'm using nginx for reverse proxy and pm2 for a supervisor. Nginx serves static files faster (node-http-proxy is good, but it more suited for other uses), and pm2 works better for me for a number of reasons.

By the way yes, you would probably want to manage your processes with a some kind of supervisor. It's quite usual to node processes to crash, and it'll be nice to have something to restart them.
 

Eric Mill

unread,
Nov 15, 2013, 2:04:57 PM11/15/13
to nod...@googlegroups.com
On Friday, November 15, 2013 4:19:25 AM UTC-5, Alex Kocharin wrote:

On Thursday, November 14, 2013 8:22:16 PM UTC+4, Eric Mill wrote:
I'm totally fine being told that the Unicorn model is the wrong way to think of things in Node. But what are the best practices

There is no such thing called "best practice". You can ask what other people do, but the best way to do something simply doesn't exist.

Yeah, yeah -- sometimes there are best practices. :)
 

for deploying a Node app where I'd like to be able to scale the number of processes up and down easily on a box? The model I'm used to is putting nginx in front, having it proxy to a Unix socket, and then having Unicorn watch the same Unix socket.

I'm aware of node-http-proxy - should I run one of these with forever -- and then also manage my express processes with forever? How should I be conceiving of the problem?

I'm using nginx for reverse proxy and pm2 for a supervisor. Nginx serves static files faster (node-http-proxy is good, but it more suited for other uses), and pm2 works better for me for a number of reasons.

I spent some time last night with "forever" and pm2. pm2 proved to have an annoying stopping bug that the author can't or won't fix, instead referring users to use the unstable 0.11 branch (which immediately produced crashes in my app). I was able to get forever working the way I wanted to, so that's what I'm going with for now. pm2 seems nice, and more like the future, but it's also heavy and seems to have a larger code surface.
 
By the way yes, you would probably want to manage your processes with a some kind of supervisor. It's quite usual to node processes to crash, and it'll be nice to have something to restart them.

Yeah, unicorn's model is helpful for this. Phusion Passenger supports Node, but the free version only supports recompiling nginx with Passenger inside, an idea I hate. You can get the unicorn-like unix socket model for Node if you pay them money for their Enterprise version. 

If anyone knows of any free Node-optimized alternatives to forever and pm2, let me know. forever is good, but it could be better.

-- Eric

 
 

Matt

unread,
Nov 15, 2013, 3:00:04 PM11/15/13
to nod...@googlegroups.com
Frankly I just use runit. Others get on fine with upstart. Frankly I do not want my process supervisor written in Node - what if you have a buggy version of Node installed by accident and everything fails?

While neither manage things like graceful restarts or clustering, those things are trivial to add to your node app.


--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Alex Kocharin

unread,
Nov 15, 2013, 3:11:44 PM11/15/13
to nod...@googlegroups.com

On Friday, November 15, 2013 11:04:57 PM UTC+4, Eric Mill wrote:
On Friday, November 15, 2013 4:19:25 AM UTC-5, Alex Kocharin wrote:

On Thursday, November 14, 2013 8:22:16 PM UTC+4, Eric Mill wrote:
I'm totally fine being told that the Unicorn model is the wrong way to think of things in Node. But what are the best practices

There is no such thing called "best practice". You can ask what other people do, but the best way to do something simply doesn't exist.

Yeah, yeah -- sometimes there are best practices. :)

This is nonsense. You can say that X is better than Y under a number of conditions. But you can't say that X is best without providing an explicit set of possibilities where X is best. It just doesn't make sense.

I can say that 3 is greater than 2. I can say that 3 is a greatest number in a set {1,2,3}. But if I say "3 is a greatest number", I would look like an idiot. Same thing with those "best practices".
 

for deploying a Node app where I'd like to be able to scale the number of processes up and down easily on a box? The model I'm used to is putting nginx in front, having it proxy to a Unix socket, and then having Unicorn watch the same Unix socket.

I'm aware of node-http-proxy - should I run one of these with forever -- and then also manage my express processes with forever? How should I be conceiving of the problem?

I'm using nginx for reverse proxy and pm2 for a supervisor. Nginx serves static files faster (node-http-proxy is good, but it more suited for other uses), and pm2 works better for me for a number of reasons.

I spent some time last night with "forever" and pm2. pm2 proved to have an annoying stopping bug that the author can't or won't fix, instead referring users to use the unstable 0.11 branch (which immediately produced crashes in my app). I was able to get forever working the way I wanted to, so that's what I'm going with for now. pm2 seems nice, and more like the future, but it's also heavy and seems to have a larger code surface.

Stopping bug is NOT a pm2 bug, but a node core bug. And node core team won't fix it in stable branch because it involves a lot of subtle changes in cluster module.

Anyway, it involves cluster module, and it's a feature that forever doesn't even have. If you just want a forever-like functionality, you can use 'fork' mode, I believe it's '-x' argument there.

I used forever before, and the biggest issue with it was the fact that it was constantly breaking on unstable, and it took months to fix every time. Plus a nasty native dependency. Well... I guess they fixed it, so nevermind.
 
 
By the way yes, you would probably want to manage your processes with a some kind of supervisor. It's quite usual to node processes to crash, and it'll be nice to have something to restart them.

Yeah, unicorn's model is helpful for this. Phusion Passenger supports Node, but the free version only supports recompiling nginx with Passenger inside, an idea I hate. You can get the unicorn-like unix socket model for Node if you pay them money for their Enterprise version. 

I don't know what do you mean by "unicorn model", but something tells me that you can do the same with built-in 'cluster' module in node.
 
If anyone knows of any free Node-optimized alternatives to forever and pm2, let me know. forever is good, but it could be better.


What exactly could be better there?

Hongli Lai

unread,
Nov 16, 2013, 6:48:19 AM11/16/13
to nod...@googlegroups.com
On Friday, November 15, 2013 8:04:57 PM UTC+1, Eric Mill wrote:
Yeah, unicorn's model is helpful for this. Phusion Passenger supports Node, but the free version only supports recompiling nginx with Passenger inside, an idea I hate. You can get the unicorn-like unix socket model for Node if you pay them money for their Enterprise version. 

This is not true. The open source version also supports the Standalone mode, which does not require recompiling Nginx. You can put Standalone behind a reverse proxy, thus utilizing the Unicorn-like Unix socket model. Most Passenger features are available in the open source version.

Take a look at the Passenger Node.js tutorial, specifically section "How does it work?". You will see that Passenger is Unix! It is a traditional process supervising forking server model.

Nuno Job

unread,
Nov 16, 2013, 7:14:11 AM11/16/13
to nod...@googlegroups.com
check mon-group and mon.

Hongli Lai

unread,
Nov 16, 2013, 7:15:39 AM11/16/13
to nod...@googlegroups.com
On Thursday, November 14, 2013 5:22:16 PM UTC+1, Eric Mill wrote:
I'm totally fine being told that the Unicorn model is the wrong way to think of things in Node. But what are the best practices for deploying a Node app where I'd like to be able to scale the number of processes up and down easily on a box? The model I'm used to is putting nginx in front, having it proxy to a Unix socket, and then having Unicorn watch the same Unix socket.

I'm aware of node-http-proxy - should I run one of these with forever -- and then also manage my express processes with forever? How should I be conceiving of the problem?

With "the Unicorn model" I believe you are referring to the supervising, preforking server model, in which there is a master process that sets up the server socket, and then forks off multiple worker processes that each one listen on that server socket. The kernel then load balances requests between the worker processes. This single server socket is then attached to Nginx in the form of a reverse proxy. In a proper implementation of this model, a crashing worker process will be automatically restarted.

I don't know why you were told that that model is the wrong way to think of things in Node. That is in fact a very good model for Node, and for web apps in general! This model allows you to scale the number of processes up and down (of course, assuming that the system actually implements it).

First off, full disclosure: I am one of the Phusion Passenger authors. This "Unicorn model" is almost exactly what Phusion Passenger implements. It supervises all your processes. It restarts them when they crash. It allows you to scale the number of processes up and down with ease. It provides I/O security by buffering your requests and responses.

How's Passenger any different compared to using 'cluster', pm2 etc and then attaching the result to an Nginx reverse proxy? Well, Passenger drastically reduces deployment complexity, and adds important production features that you can't easily get by just attaching Node to Nginx:
  • Using Passenger is much easier. If you do it yourself, you’ll have to write reverse proxy rules, write init scripts, etc. The result probably does not even handle corner cases properly, like race conditions, stale PID files, etc. Passenger takes care of all this for you and handles virtually all the corner cases. This reduces the number of moving parts and reduces complexity.
  • Passenger integrates much deeper into Nginx than a straight reverse proxy does, and as such can leverage Nginx features much better. For example, the load balancing and response buffering in Phusion Passenger is much better than the one you get with manual reverse proxying.
  • By using Nginx’s proxy module, it’s very hard to see what’s going on with the system right now. Are all connections ok? Are all processes ok? Phusion Passenger provides simple and powerful administration tools that can help you with that.
Passenger is proven technology: it's already being used by the likes of New York Times, Pixar, AirBnB, Apple, American Express, Juniper, etc as well as over 350.000 websites.

I see that there are some misunderstandings about Passenger. It is not true that Passenger requires Nginx recompilation. The fact is:
  • Passenger provides a Standalone mode. You configure Passenger through command line options. Passenger Standalone is powered by an internal Nginx core and you get all the Passenger features. This Nginx core is fully internal and is precompiled -- you don't have to recompile your existing Nginx! Because it's powered by this Nginx core, you can choose to directly expose it to port 80, and it's immediately production ready. You can also attach it to an existing Nginx using a reverse proxy if you want to integrate it into your current infrastructure.
  • Passenger provides an optional Nginx integration mode which allows Passenger to start together with Nginx, and which allows you to configure Passenger inside the Nginx config file. It's all about ease and reducing complexity: instead of having to think and deal with yet another software component, you just deal with Nginx and treat it as if it can manage Node. If you want to use this mode (which you don't have to), then Passenger must be compiled into Nginx. But even then, you don't have to do that yourself! We provide Debian and Ubuntu packages, so it's just an apt-get upgrade away.
  • All of the above are available in the open source version.
More information can be found in the Passenger Node.js tutorial: https://github.com/phusion/passenger/wiki/Phusion-Passenger%3A-Node.js-tutorial

There's a strong support community around Passenger too. Almost every question can be answered by contacting the discussion forum, Stack Overflow, etc. There is also a ton of extremely detailed documentation at https://www.phusionpassenger.com/documentation_and_support.

As one of its authors, I take pride in writing excellent documentation and making Passenger ease and stable. I guarantee that it's fit for production. If you're not satisfied with it, you get your money back, literally.

Alex Kocharin

unread,
Nov 16, 2013, 8:26:45 AM11/16/13
to nod...@googlegroups.com

On Saturday, November 16, 2013 4:15:39 PM UTC+4, Hongli Lai wrote:
With "the Unicorn model" I believe you are referring to the supervising, preforking server model, in which there is a master process that sets up the server socket, and then forks off multiple worker processes that each one listen on that server socket. The kernel then load balances requests between the worker processes. This single server socket is then attached to Nginx in the form of a reverse proxy. In a proper implementation of this model, a crashing worker process will be automatically restarted.
 
Sounds much like built-in cluster module. In fact, it sounds exactly like built-in cluster module. Thanks, I understand now what it means. :)

 
First off, full disclosure: I am one of the Phusion Passenger authors. This "Unicorn model" is almost exactly what Phusion Passenger implements. It supervises all your processes. It restarts them when they crash.

pm2. forever+cluster. Nothing new here.


It allows you to scale the number of processes up and down with ease. It provides I/O security by buffering your requests and responses.

I fail to see where security is added. Only thing buffering does is that it adds memory consumption, not security.


How's Passenger any different compared to using 'cluster', pm2 etc and then attaching the result to an Nginx reverse proxy? Well, Passenger drastically reduces deployment complexity, and adds important production features that you can't easily get by just attaching Node to Nginx:

If you want to reduce deployment complexity, you can just bind your node app to 80th port.

Nginx is there to increase flexibility, add failovers and all that stuff. All this complexity nginx adds is necessary, and you can't really reduce it without losing flexibility. It's not apache, it's not haproxy, nginx config is already as simple as it can possibly be.
 
  • Using Passenger is much easier. If you do it yourself, you’ll have to write reverse proxy rules, write init scripts, etc. The result probably does not even handle corner cases properly, like race conditions, stale PID files, etc. Passenger takes care of all this for you and handles virtually all the corner cases. This reduces the number of moving parts and reduces complexity.
I believe pm2 does all that. Not quite sure because I prefer to write reverse proxy rules and init scripts by hand to get a better understanding of the system. So, nothing really new here.

  • Passenger integrates much deeper into Nginx than a straight reverse proxy does, and as such can leverage Nginx features much better. For example, the load balancing and response buffering in Phusion Passenger is much better than the one you get with manual reverse proxying.
1) Load balancing is done using 'cluster' module. It is as good as it could possibly be. If it's not, I'm sure node core team will accept a patch.
2) Best buffering is non-existent buffering. Reverse proxy shouldn't even do that except for a very good reason.
 
  • By using Nginx’s proxy module, it’s very hard to see what’s going on with the system right now. Are all connections ok? Are all processes ok? Phusion Passenger provides simple and powerful administration tools that can help you with that.
It has nothing to do with nginx proxy module. Both forever and pm2 allow to monitor processes, and pm2 has a nice json api on top of that to develop custom admin tools.

 
Passenger is proven technology: it's already being used by the likes of New York Times, Pixar, AirBnB, Apple, American Express, Juniper, etc as well as over 350.000 websites.

Over 350000 Ruby websites, right? Because I don't remember it being used in any more or less widely known node.js applications.
 

I see that there are some misunderstandings about Passenger. It is not true that Passenger requires Nginx recompilation. The fact is:
  • Passenger provides a Standalone mode. You configure Passenger through command line options. Passenger Standalone is powered by an internal Nginx core and you get all the Passenger features. This Nginx core is fully internal and is precompiled -- you don't have to recompile your existing Nginx! Because it's powered by this Nginx core, you can choose to directly expose it to port 80, and it's immediately production ready. You can also attach it to an existing Nginx using a reverse proxy if you want to integrate it into your current infrastructure.
Wait, wait... Are you distributing your own patched nginx version? It doesn't sound simple at all. But I admit, a suggestion about using "nginx -> passenger -> node.js" is kinda funny. I guess 3 servers instead of 2 really reduce complexity.

  • Passenger provides an optional Nginx integration mode which allows Passenger to start together with Nginx, and which allows you to configure Passenger inside the Nginx config file. It's all about ease and reducing complexity: instead of having to think and deal with yet another software component, you just deal with Nginx and treat it as if it can manage Node. If you want to use this mode (which you don't have to), then Passenger must be compiled into Nginx. But even then, you don't have to do that yourself! We provide Debian and Ubuntu packages, so it's just an apt-get upgrade away.
So, it doesn't exist in a standard debian repository like nginx or node.js does? Oh well...

  • All of the above are available in the open source version.
Which means that there is a non-opensource version somewhere. Which means an opensource version probably have some limitations, and if I run into it, I will be forced to buy enterprise version. Oh well...

Eric Mill

unread,
Nov 16, 2013, 12:03:06 PM11/16/13
to nod...@googlegroups.com
On Sat, Nov 16, 2013 at 8:26 AM, Alex Kocharin <al...@equenext.com> wrote:

On Saturday, November 16, 2013 4:15:39 PM UTC+4, Hongli Lai wrote:
With "the Unicorn model" I believe you are referring to the supervising, preforking server model, in which there is a master process that sets up the server socket, and then forks off multiple worker processes that each one listen on that server socket. The kernel then load balances requests between the worker processes. This single server socket is then attached to Nginx in the form of a reverse proxy. In a proper implementation of this model, a crashing worker process will be automatically restarted.
 
Sounds much like built-in cluster module. In fact, it sounds exactly like built-in cluster module. Thanks, I understand now what it means. :)

The Cluster module is still at stability level 1, in the docs. And the pm2 bug I mentioned that pointed me to the unstable branch was a little unsettling.

 
Passenger integrates much deeper into Nginx than a straight reverse proxy does, and as such can leverage Nginx features much better. For example, the load balancing and response buffering in Phusion Passenger is much better than the one you get with manual reverse proxying.
1) Load balancing is done using 'cluster' module. It is as good as it could possibly be. If it's not, I'm sure node core team will accept a patch.

Submitting a patch to node core is incredibly daunting to me (I'm an experienced web dev, but know basically no C), so I'd really like to see the cluster module become more stable first.
 

I see that there are some misunderstandings about Passenger. It is not true that Passenger requires Nginx recompilation. The fact is:
  • Passenger provides a Standalone mode. You configure Passenger through command line options. Passenger Standalone is powered by an internal Nginx core and you get all the Passenger features. This Nginx core is fully internal and is precompiled -- you don't have to recompile your existing Nginx! Because it's powered by this Nginx core, you can choose to directly expose it to port 80, and it's immediately production ready. You can also attach it to an existing Nginx using a reverse proxy if you want to integrate it into your current infrastructure.
Wait, wait... Are you distributing your own patched nginx version? It doesn't sound simple at all. But I admit, a suggestion about using "nginx -> passenger -> node.js" is kinda funny. I guess 3 servers instead of 2 really reduce complexity.

I did misread the docs, and missed that Standalone mode is free. However, it doesn't actually feel very standalone, shipping with nginx compiled inside it -- it's the same clunky situation as non-Standalone mode! You've just made it easier to forget that the problem is there. 
 
Looking closer, I see Passenger continues to impose requirements on my app's structure (app.js, a public dir, a tmp dir). Those kinds of requirements, that either straitjacket you or force you to manage vestigial filesystem cruft, were very nice to leave behind when I moved from Passenger to Unicorn in my Ruby apps years ago, and in leaving Capistrano behind for Fabric.
 
 
As one of its authors, I take pride in writing excellent documentation and making Passenger ease and stable. I guarantee that it's fit for production. If you're not satisfied with it, you get your money back, literally.

I think Phusion really needs to re-think its approach with the Node community. After evaluating Phusion, forever, and pm2, I'm leaning more strongly towards forever or pm2 simply because they do less work, are more cleanly decoupled, and I can understand their entire role more clearly.

So right now, I've got my app deployed using forever. It's not as flexible as pm2, but some of pm2's power is clearly relying on non-stable code in Node core. 

It feels to me like the Node community has still not settled on some simple, stable best practices for deploying web apps. There are a few good starts that accomplish most of what people want, but there are rough edges everywhere. Maybe this is because Node came about when PaaS-es were already well established, and so services like Heroku and Nodejitsu have lowered the pressure for the community to produce these solutions and to have large numbers of people depend on them every day.

-- Eric
 

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Hongli Lai

unread,
Nov 16, 2013, 2:15:26 PM11/16/13
to nod...@googlegroups.com
On Sat, Nov 16, 2013 at 6:03 PM, Eric Mill <er...@konklone.com> wrote:
> I did misread the docs, and missed that Standalone mode is free. However, it
> doesn't actually feel very standalone, shipping with nginx compiled inside
> it -- it's the same clunky situation as non-Standalone mode! You've just
> made it easier to forget that the problem is there.

Hi Eric.

Actually the standalone mode *is* fully standalone. The fact that it
is powered by an Nginx core is an implementation detail. As a user,
you never have to deal with it directly. Using the standalone mode you
never have to touch the Nginx config file, or start/stop Nginx, etc.
There is only the 'passenger' command.

I understand that you might *feel* that it is not standalone because
there is an Nginx in it. But consider what the alternative would be:
to implement an HTTP server ourselves. And why would we want to do
that? Nginx is awesome, it's a wonderful HTTP server. Why reimplement
the wheel? Reusing Nginx makes a lot of sense. The result is still
small and lightweight.

It is also not "a patched Nginx". It is just Nginx, with an extra
module added to it.

Of course, if you have specific criticisms against the implementation,
I'm very open to hearing them. Passenger is under active development
and any issues can be addressed.


> Looking closer, I see Passenger continues to impose requirements on my app's
> structure (app.js, a public dir, a tmp dir). Those kinds of requirements,
> that either straitjacket you or force you to manage vestigial filesystem
> cruft, were very nice to leave behind when I moved from Passenger to Unicorn
> in my Ruby apps years ago, and in leaving Capistrano behind for Fabric.

These requirements are merely conventions. If you do not like these
requirements, they can easily be made optional in the next version (a
few weeks from now). Would you like me to go ahead and do so?

You believe that Passenger does too much and is too tightly coupled. I
am stressing the point that that is merely in appearance only. Code
speaks louder than words, so if you have any specific concerns, I'm
all ears.

--
Phusion | Ruby & Rails deployment, scaling and tuning solutions

Web: http://www.phusion.nl/
E-mail: in...@phusion.nl
Chamber of commerce no: 08173483 (The Netherlands)

Hongli Lai

unread,
Nov 16, 2013, 3:02:57 PM11/16/13
to nod...@googlegroups.com
On Sat, Nov 16, 2013 at 8:15 PM, Hongli Lai <hon...@phusion.nl> wrote:
>> Looking closer, I see Passenger continues to impose requirements on my app's
>> structure (app.js, a public dir, a tmp dir). Those kinds of requirements,
>> that either straitjacket you or force you to manage vestigial filesystem
>> cruft, were very nice to leave behind when I moved from Passenger to Unicorn
>> in my Ruby apps years ago, and in leaving Capistrano behind for Fabric.
>
> These requirements are merely conventions. If you do not like these
> requirements, they can easily be made optional in the next version (a
> few weeks from now). Would you like me to go ahead and do so?
>
> You believe that Passenger does too much and is too tightly coupled. I
> am stressing the point that that is merely in appearance only. Code
> speaks louder than words, so if you have any specific concerns, I'm
> all ears.

I went ahead and did it anyway. And here you go! :)
https://github.com/phusion/passenger/wiki/Free-style-Node.js-structure
https://github.com/phusion/passenger/commit/dee9f51ffb2dde415231507b88c322971169d650

Eric Mill

unread,
Nov 16, 2013, 3:29:59 PM11/16/13
to nod...@googlegroups.com
Well, that's extremely responsive, I appreciate that. I can't promise it means that I'm going to switch to Phusion, but I will be continuing to try different things over the next few weeks, and this definitely helps.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Evan

unread,
Nov 16, 2013, 3:38:43 PM11/16/13
to nod...@googlegroups.com
To me, when I read "unicorn model", I look at it as a combination of 2 things: 
- a master-slave relationship which allows for multiple servers to share a port/socket in order to load balance
- a signaling pattern to manage the whole thing.  

As others have pointed out, node's built-in cluster module already handles part 1 for you really nicely.  What might not be so obvious up front is that children in a cluster can share *any* socket, not just HTTP connections.  One of the trickier things unicorn does which you can do simply in node is monitor the health of the child processes.  You get events for children booting and dying so you can tell if you should spawn a new worker, etc. 

I was heavily influenced by Unicorn's design and signal patterns when I implemented actionHero's cluster module.  At it's heart is is just a wrapper around `cluster` with some signal handling.  The trickier part was actually building my application to be comfortable in transitional states.  For example, if the TCP/TLS server was signaled to shut down, it needs to ignore all incoming new connections and send a 'goodbye' message to all existing ones.  It's nothing overly complicated, but it's a little more to keep in mind when developing, assuming your goal is 0-downtime deployments.  

All in all, I really like Unicorn's patterns.  It makes it possible to 'roll' code without taking your server down, signal that you need more or less workers, and have a single parent application to monitor and control everything.  That said, I tend to always keep nginx in front of *every* application I create (regardless of language) to handle static assets, rate-limit, etc.  

Hongli Lai

unread,
Nov 16, 2013, 3:58:15 PM11/16/13
to nod...@googlegroups.com
On Sat, Nov 16, 2013 at 9:29 PM, Eric Mill <er...@konklone.com> wrote:
> Well, that's extremely responsive, I appreciate that. I can't promise it
> means that I'm going to switch to Phusion, but I will be continuing to try
> different things over the next few weeks, and this definitely helps.

Sure, I'm glad you'd be willing to give Passenger another chance. I
understand that since you moved away from Passenger in the past, that
you'd be more skeptical now. And for good reason; the points you
raised regarding imposing a structure etc are very valid. As much as
I'd hate to admit, we did fail in a number of areas in the past by not
making things configurable enough, or making things too magical.

But we've learned a lot since those times, and we kept improving
Passenger as well as learning from Unicorn. Unicorn is wonderful
wonderful technology and Eric Wong is a brilliant guy. We even
contributed to Unicorn because we liked its design so much, and
introduced a lot of improvements in Unicorn back to Passenger, with
further improvements. For example the recent out-of-band garbage
collection work in Passenger is inspired by Unicorn. Many parts in
Passenger 4 are complete redesigns compared to earlier versions.

In the end, you should use whatever technology fits your needs best.
Maybe that's Passenger, or maybe not, which is also fine. :) In any
case we'll keep on improving Passenger and advancing the state of
things.

Matt

unread,
Nov 16, 2013, 8:53:49 PM11/16/13
to nod...@googlegroups.com

On Sat, Nov 16, 2013 at 3:38 PM, Evan <evant...@gmail.com> wrote:
I was heavily influenced by Unicorn's design and signal patterns when I implemented actionHero's cluster module.  At it's heart is is just a wrapper around `cluster` with some signal handling.  The trickier part was actually building my application to be comfortable in transitional states.  For example, if the TCP/TLS server was signaled to shut down, it needs to ignore all incoming new connections and send a 'goodbye' message to all existing ones.  It's nothing overly complicated, but it's a little more to keep in mind when developing, assuming your goal is 0-downtime deployments.  

But the cluster module handles this via worker.disconnect(). Zero downtime updates are just a matter of spawning a new set of children and telling your current ones to .disconnect().

Evan

unread,
Nov 16, 2013, 9:22:39 PM11/16/13
to nod...@googlegroups.com
@matt I guess it really depends on your application logic.  My understanding of cluster.disconnect is that the worker/child will instantly close all open sockets/pipes/etc.  That means that if you have a client mid-request, that request will timeout.  I don't think the client will see a true connection failure, as they are technically connecting `via` the cluster master, and the socket (as far as they can see) will remain open.  This kind of thing gets dangerous if you are mid-database operation or similar.  

Mario Pareja

unread,
Nov 17, 2013, 11:51:34 AM11/17/13
to nod...@googlegroups.com
On Tuesday I'd like to buy you plenty of beers and pick your brain about some these ops issues!

Mario

Matt

unread,
Nov 17, 2013, 3:25:33 PM11/17/13
to nod...@googlegroups.com

On Sat, Nov 16, 2013 at 9:22 PM, Evan <evant...@gmail.com> wrote:
@matt I guess it really depends on your application logic.  My understanding of cluster.disconnect is that the worker/child will instantly close all open sockets/pipes/etc.  That means that if you have a client mid-request, that request will timeout.  I don't think the client will see a true connection failure, as they are technically connecting `via` the cluster master, and the socket (as far as they can see) will remain open.  This kind of thing gets dangerous if you are mid-database operation or similar.  

Nope, that's not how worker.disconnect() works.

It just tells the master to not send any more connections to that child, allowing it to gracefully exit. Now of course if the child has some other reason to stick around (a setInterval or an outbound connection somewhere) then it will do so, but you need to take care of that in any system which supports graceful restarts.

Matt.

Evan Tahler

unread,
Nov 17, 2013, 4:13:34 PM11/17/13
to nod...@googlegroups.com
Ahh! Thanks for clearing that up.

--
--
Job Board: http://jobs.nodejs.org/
Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com
To unsubscribe from this group, send email to
nodejs+un...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en
 
---
You received this message because you are subscribed to a topic in the Google Groups "nodejs" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/nodejs/PiG9kQ9u-CU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to nodejs+un...@googlegroups.com.

greelgorke

unread,
Nov 18, 2013, 3:55:10 AM11/18/13
to nod...@googlegroups.com
for http/s node apps there is also https://npmjs.org/package/up-time which i liked pretty much.

Hongli Lai

unread,
Nov 27, 2013, 9:48:51 AM11/27/13
to nod...@googlegroups.com
On Sat, Nov 16, 2013 at 6:03 PM, Eric Mill <er...@konklone.com> wrote:
>> Wait, wait... Are you distributing your own patched nginx version? It
>> doesn't sound simple at all. But I admit, a suggestion about using "nginx ->
>> passenger -> node.js" is kinda funny. I guess 3 servers instead of 2 really
>> reduce complexity.
>
> I did misread the docs, and missed that Standalone mode is free. However, it
> doesn't actually feel very standalone, shipping with nginx compiled inside
> it -- it's the same clunky situation as non-Standalone mode! You've just
> made it easier to forget that the problem is there.

Eric, Alex, I'm happy to tell you that we've just removed Nginx from
Passenger Standalone. This should alleviate any concerns about
simplicity and standaloneness. This change will be included in the next
version, 2.0.26, which should be released at most a few weeks from
now.
Reply all
Reply to author
Forward
0 new messages