86

There are many tutorials on how to configure nginx to cooperate with uWGSI when I want to deploy Django application.

But why do I need nginx in this kit? uWSGI itself can serve WSGI Python applications, it can serve static files, it can also do SSL. What can nginx do which uWSGI can not?

user983447
  • 1,107
  • 1
  • 10
  • 10
  • 16
    I can see that this question is closed as opinion based. I absolutely disagree. Question "What can nginx do which uWSGI can not?" is fact based. – user983447 May 04 '14 at 05:54
  • 2
    I don't generally speak for reopenings, but in this case I agree. The existing upvoted-and-accepted answer is a good one, which shows that the question, as written, admits of sensible and relevant answers; I think that probably makes it a good question. – MadHatter May 04 '14 at 06:00

2 Answers2

72

You don't.

That's the simple answer, anyway -- you don't need it. uWSGI is itself a capable server.

However, other servers like nginx have been around longer and are (probably, anyway) more secure, as well as having additional features not supported by uWSGI -- for example, improved handling of static resources (via any combination of Expires or E-Tag headers, gzip compression, pre-compressed gzip, etc.) that can significantly reduce server and network load; additionally, a server like nginx in front of your Django application can implement caching of your dynamic content as well, further helping to reduce server load, and even helping to facilitate the use of a CDN (which normally don't do well with dynamic content). You could even go further and have nginx on a completely separate server, reverse proxying requests for dynamic content to a load balanced cluster of application servers while handling the static content itself.

For example, my blog (while it is WordPress, it does have nginx in front of it) is tuned to cache posts for 24 hours, and to cache index pages for 5 minutes; while I don't see enough traffic for that to really matter most of the time, it helps my tiny little VPS weather the occasional surge that might otherwise knock it down -- such as the big surge of traffic when one of my articles got picked up by a Twitterer with many thousands of followers, many of whom re-tweeted it to their thousands of followers.

If I had been running a "bare" uWSGI server (and assuming it had been a Django site, rather than WordPress), it might have stood up to it just fine -- or it might have crashed and burned, costing me in missed visitors. Having nginx in front of it to handle that load can really help.

All that being said, if you're just running a little site that won't see a lot of traffic, there's no real need for nginx or anything else -- just use uWSGI on its own if that's what you want to do. On the other hand, if you'll see a lot of traffic... well, you still might want uWSGI, but you should at least consider something in front of it to help with the load. Actually, you should really be load-testing different configurations with your finished site to determine what does work best for you under your expected load, and use whatever that ends up being.

Kromey
  • 3,621
  • 4
  • 24
  • 30
  • 4
    The one thing that comes to mind that I think is worth noting in addition to what @Kromey covered in their answer is that the native protocol for uWSGI is not http but the uwsgi protocol. The uwsgi protocol is simpler and more efficient to deal with than http and thus sticking a more full-featured web server (nginx or whatnot) in front of your uWSGI application does not actually duplicate a lot of processing and may provide significant benefits depending on your needs. – Håkan Lindqvist Apr 23 '14 at 17:38
  • 1
    @HåkanLindqvist is absolutely correct; just to clarify, uWSGI is fully capable of "speaking" HTTP, however, so can stand on its own just fine, but yes it is well worth noting that a web server in front of it would use the uwsgi protocol, not HTTP, to speak to uWSGI, and therefore, yes, very little duplication of the processing involved. – Kromey Apr 23 '14 at 18:04
  • 2
    This is a fine answer, however, it could be improved with a link to uWSGI's own documentation on the topic, which explains with more specifics what you *can* do with uWSGI: http://uwsgi-docs.readthedocs.io/en/latest/HTTP.html#can-i-use-uwsgi-s-http-capabilities-in-production – Tobias McNulty Mar 22 '17 at 05:28
  • The answer starts off by saying you don't need nginx in front of uWGSI and then proceeds to explain why you do. So perhaps the correct answer is you don't need nginx for small applications but you do need nginx for largers apps? – ZuLu Jan 18 '22 at 15:36
5

IMO, if you put your website in Internet instead of Lab, you might see the difference.

Imagine an user from another country with low network speed open web browser to access your website. uWSGI will handle that Http connection in a thread. That thread may spend pretty long time to wait for a complete Http request due to low network speed. If your thread pool size is 100, imagine 100 users like that slow, what will happen? No idle thread to handle other Http request.

But things quite different for Nginx. Nginx is designed in 'Reactor Pattern'. You could google 'Reactor Pattern' to see how it works. In short, slow speed connection does not affect it to handle other Http requests.

Jcyrss
  • 161
  • 1
  • 3
  • 2
    I doubt using Nginx is going to change that. When a Django application is hosted on Apache using WSGI, the view function will be called before any POST data is read from a socket. So if the client is slow, it will occupy a thread from the request has been received until the POST data has been received. Why would replacing Apache with Nginx change that? – kasperd May 26 '15 at 12:58
  • 3
    As what I know, by default, Nginx will not proxy HTTP request to backend application server until it get a complete HTTP request. So for applicaton server like Django, what they got is always a fast HTTP connetion and request, no time wasted on waiting for a complete http request, after handling quest soon, the running thread could be idle for next Http request soon. – Jcyrss May 27 '15 at 05:10
  • 2
    It is called request buffering, which is enabled by default in Nginx (in older versions of Nginx it was not possible to turn this off): http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_request_buffering – Tobias McNulty Mar 22 '17 at 05:25