Overly simplified: You need something that executes Python but Python isn't the best at handling all types of requests.
[disclaimer: I'm a Gunicorn developer]
Less simplified: Regardless of what app server you use (Gunicorn, mod_wsgi, mod_uwsgi, cherrypy) any sort of non-trivial deployment will have something upstream that will handle the requests that your Django app should not be handling. Trivial examples of such requests are serving static assets (images/css/js).
This results in two first tiers of the classic "three tier architecture". Ie, the webserver (Nginx in your case) will handle many requests for images and static resources. Requests that need to be dynamically generated will then be passed on to the application server (Gunicorn in your example). (As an aside, the third of the three tiers is the database)
Historically speaking, each of these tiers would be hosted on separate machines (and there would most likely be multiple machines in the first two tiers, ie: 5 web servers dispatch requests to two app servers which in turn query a single database).
In the modern era we now have applications of all shapes and sizes. Not every weekend project or small business site actually needs the horsepower of multiple machines and will run quite happily on a single box. This has spawned new entries into the array of hosting solutions. Some solutions will marry the app server to the web server (Apache httpd + mod_wsgi, Nginx + mod_uwsgi, etc). And its not at all uncommon to host the database on the same machine as one of these web/app server combinations.
Now in the case of Gunicorn, we made a specific decision (copying from Ruby's Unicorn) to keep things separate from Nginx while relying on Nginx's proxying behavior. Specifically, if we can assume that Gunicorn will never read connections directly from the internet, then we don't have to worry about clients that are slow. This means that the processing model for Gunicorn is embarrassingly simple.
The separation also allows Gunicorn to be written in pure Python which minimizes the cost of development while not significantly impacting performance. It also allows users the ability to use other proxies (assuming they buffer correctly).
As to your second question about what actually handles the HTTP request, the simple answer is Gunicorn. The complete answer is both Nginx and Gunicorn handle the request. Basically, Nginx will receive the request and if it's a dynamic request (generally based on URL patterns) then it will give that request to Gunicorn, which will process it, and then return a response to Nginx which then forwards the response back to the original client.
So in closing, yes. You need both Nginx and Gunicorn (or something similar) for a proper Django deployment. If you're specifically looking to host Django with Nginx, then I would investigate Gunicorn, mod_uwsgi, and maybe CherryPy as candidates for the Django side of things.
Having just completed an app involving lots of nginx reverse proxying, I would be more inclined to go with either your second or third option. ...or maybe something slightly different. Lets break it down to individual points to consider:
Static Files
For serving static files (for either the website or the app), node and nginx are the clear choices as they don't fork themselves for each new request like Apache does. Node is faster than nginx at serving static files, but depending on the amount of traffic you'll see, this might not be a meaningful difference.
I would choose nginx as the public-facing server and reverse proxy requests to other things as necessary. Even though it is slightly slower than node at serving static files, its flexibility and ease of configuration make up for it. PHP, if you choose to use it, is faster (configured properly) with nginx than with Apache, and nginx's configuration files are similar to Apache's but more concise. It shouldn't be too foreign-looking when you dive into it.
SSL
If you are planning to use SSL, save yourself the trouble now and get the latest version of nginx so that you can utilize the latest version of Google's SPDY module. Currently, the latest version is 1.7.3. Some package managers are behind quite a bit, so you may have to compile from source. If this is the case, make sure that the --with-http_spdy_module --with-http_ssl_module
flags are used, among others. Here is a guide for that as well as setting up the configuration files to use SPDY.
Because all your requests go through nginx and a single domain name, you only have to set up SSL in one place. Any reverse proxied requests do not need to be over HTTPS because they happen internally. If you make node.js run your app, you just have to make sure it only listens on localhost and doesn't serve external requests directly.
Application
Node is a good choice for the application code and the long polling that you wish to accomplish. It is also fairly straightforward to proxy these long polling requests through nginx. With these two nginx options...
client_body_timeout 1m;
client_header_timeout 1m;
... you can adjust the timeout of requests. You will want to make sure your application code puts an end to the requests before nginx does. Otherwise, you will get a 504 Gateway Timeout
instead of a 200 ok
. If the nginx timeout is set to 60 seconds, you should end and restart a long polling request every 55 seconds or so.
Website
If you aren't set in stone with using PHP, node.js or a static site generator written in node.js could also work for your needs. Docpad is one that I use, but there are many great options. Node packages like Grunt make deployment automation easy. A few of the things I use it for are HTML, CSS, and JavaScript minification and cache busting.
Best Answer
Take a look at this post: http://bergie.iki.fi/blog/dnode-make_php_and_node-js_talk_to_each_other/
You could make a simple communicating script on
node.mydomain.com
and have the NodeJS server listen on another port.Else you can also
proxy_redirect http://node.mydomain.com http://mydomain:8080/;
so here you have to run the NodeJS on another port, too.