So from the Python/Flask docs, they both recommend not running the Flask web server as the production web server which makes sense. My question is, am I then able to run my Flask application on top of an Nginx server? Why do all the guides on the internet recommend wrapping Flask around uWSGI, Tornado, or some other WSGI server? What does it mean for something to be WSGI? Isn't Flask WGSI compliant?
I am particularly lost because here, the first response states:
Apache and Nginx are both HTTP servers.They can serve static files like
(.jpg and .html files) or dynamic pages (like a Wordpress blog or forum written in a language like PHP or Python).
However this post states:
Nginx is a web server. It serves static files, however it cannot execute and host
Python application. uWSGI fills that gap.
It just seems inefficient for my application to be handled by a server (ex: uWSGI) and then another server (ex: Nginx).
Nginx is a web server and is concerned with web server stuff, not with how to run Python programs. uWSGI is an application server and knows how to speak WSGI with Python (and other languages now). Both Nginx and uWSGI speak the uWSGI protocol, which is an efficient protocol over UNIX sockets.
Nginx deals with http requests from/responses to the outside world (possibly load balancing, caching, etc.). Your Flask application deals with WSGI requests/responses. uWSGI knows how to start your application (possibly with multiprocessing and/or threading) and bridge the gap between HTTP and WSGI.
There are other HTTP servers besides Nginx, and other WSGI servers besides uWSGI, but they all use the same workflow: the HTTP server passes to the WSGI server, which manages your application process and passes back to the HTTP server.
This setup is known as a reverse proxy. It allows each tool to do what it's good at and not be concerned about the other parts of the process. There is nothing particularly inefficient about it, until you get to truly massive scales.
Well, WSGI is a specification for interface between Python applications and web servers. uWSGI is (simply put) a realization of this specification written in C/C++. You can run almost any application on a "serious" webserver (like nginx) by just providing an entry point:
def application(env, start_response):
start_response('200 OK', [('Content-Type','text/html')])
return ["Hello World"]
and then running it like this:
uwsgi --http :9090 --wsgi-file file_with_the_code_above.py
You can return anything you want instead of ["Hello world"], of course. See http://uwsgi-docs.readthedocs.org/en/latest/WSGIquickstart.html for more.
Related
Setting up Flask with uWSGI and Nginx can be difficult. I tried following this DigitalOcean tutorial and still had trouble. Even with buildout scripts it takes time, and I need to write instructions to follow next time.
If I don't expect a lot of traffic, or the app is private, does it make sense to run it without uWSGI? Flask can listen to a port. Can Nginx just forward requests?
Does it make sense to not use Nginx either, just running bare Flask app on a port?
When you "run Flask" you are actually running Werkzeug's development WSGI server, and passing your Flask app as the WSGI callable.
The development server is not intended for use in production. It is not designed to be particularly efficient, stable, or secure. It does not support all the possible features of a HTTP server.
Replace the Werkzeug dev server with a production-ready WSGI server such as Gunicorn or uWSGI when moving to production, no matter where the app will be available.
The answer is similar for "should I use a web server". WSGI servers happen to have HTTP servers but they will not be as good as a dedicated production HTTP server (Nginx, Apache, etc.).
Flask documents how to deploy in various ways. Many hosting providers also have documentation about deploying Python or Flask.
First create the app:
import flask
app = flask.Flask(__name__)
Then set up the routes, and then when you want to start the app:
import gevent.pywsgi
app_server = gevent.pywsgi.WSGIServer((host, port), app)
app_server.serve_forever()
Call this script to run the application rather than having to tell gunicorn or uWSGI to run it.
I wanted the utility of Flask to build a web application, but had trouble composing it with other elements. I eventually found that gevent.pywsgi.WSGIServer was what I needed. After the call to app_server.serve_forever(), call app_server.stop() when to exit the application.
In my deployment, my application is listening on localhost:port using Flask and gevent, and then I have Nginx reverse-proxying HTTPS requests to it.
You definitely need something like a production WSGI server such as Gunicorn, because the development server of Flask is meant for ease of development without much configuration for fine-tuning and optimization.
Eg. Gunicorn has a variety of configurations depending on the use case you are trying to solve. But the development flask server does not have these capabilities. In addition, these development servers show their limitations as soon as you try to scale and handle more requests.
With respect to needing a reverse proxy server such as Nginx is concerned it depends on your use case.
If you are deploying your application behind the latest load balancer in AWS such as an application load balancer(NOT classic load balancer), that itself will suffice for most use cases. No need to take effort into setting up NGINX if you have that option.
The purpose of a reverse proxy is to handle slow clients, meaning clients which take time to send the request. These reverse load balancers buffer the requests till the entire request is got from the clients and send them async to Gunicorn. This improves the performance of your application considerably.
Setting up Flask with uWSGI and Nginx can be difficult. I tried following this DigitalOcean tutorial and still had trouble. Even with buildout scripts it takes time, and I need to write instructions to follow next time.
If I don't expect a lot of traffic, or the app is private, does it make sense to run it without uWSGI? Flask can listen to a port. Can Nginx just forward requests?
Does it make sense to not use Nginx either, just running bare Flask app on a port?
When you "run Flask" you are actually running Werkzeug's development WSGI server, and passing your Flask app as the WSGI callable.
The development server is not intended for use in production. It is not designed to be particularly efficient, stable, or secure. It does not support all the possible features of a HTTP server.
Replace the Werkzeug dev server with a production-ready WSGI server such as Gunicorn or uWSGI when moving to production, no matter where the app will be available.
The answer is similar for "should I use a web server". WSGI servers happen to have HTTP servers but they will not be as good as a dedicated production HTTP server (Nginx, Apache, etc.).
Flask documents how to deploy in various ways. Many hosting providers also have documentation about deploying Python or Flask.
First create the app:
import flask
app = flask.Flask(__name__)
Then set up the routes, and then when you want to start the app:
import gevent.pywsgi
app_server = gevent.pywsgi.WSGIServer((host, port), app)
app_server.serve_forever()
Call this script to run the application rather than having to tell gunicorn or uWSGI to run it.
I wanted the utility of Flask to build a web application, but had trouble composing it with other elements. I eventually found that gevent.pywsgi.WSGIServer was what I needed. After the call to app_server.serve_forever(), call app_server.stop() when to exit the application.
In my deployment, my application is listening on localhost:port using Flask and gevent, and then I have Nginx reverse-proxying HTTPS requests to it.
You definitely need something like a production WSGI server such as Gunicorn, because the development server of Flask is meant for ease of development without much configuration for fine-tuning and optimization.
Eg. Gunicorn has a variety of configurations depending on the use case you are trying to solve. But the development flask server does not have these capabilities. In addition, these development servers show their limitations as soon as you try to scale and handle more requests.
With respect to needing a reverse proxy server such as Nginx is concerned it depends on your use case.
If you are deploying your application behind the latest load balancer in AWS such as an application load balancer(NOT classic load balancer), that itself will suffice for most use cases. No need to take effort into setting up NGINX if you have that option.
The purpose of a reverse proxy is to handle slow clients, meaning clients which take time to send the request. These reverse load balancers buffer the requests till the entire request is got from the clients and send them async to Gunicorn. This improves the performance of your application considerably.
I am a .net developer coming over to python. I have recently started using Flask and have some quick questions about serving files.
I noticed a lot of tutorials focused on nginix and flask. However, I am able to run flask without nginx. I'm just curious as to why this is used together (nginx and flask). Is nginx only for static files?
Nginx is a proxy server, imagine your apps have multiples microservices on differents languagues.
For more info NGINX REVERSE PROXY
On a development machine flask can be run without a webserver (nginx, apache etc) or an application container (eg uwsgi, gunicorn etc).
Things are different when you want to handle the load on a production server. For starters python is relatively very slow when it comes to serving static content where as apache / nginx do that very well.
When the application becomes big enough to be broken into multiple separate services or has to be horizontally scaled, the proxy server capabilities of nginx come in very handy.
In the architectures I build, nginx serves as the entry point where ssl is terminates and the rest of the application is behind a VPN and firewall.
Does this help?
From http://flask.pocoo.org/docs/1.0/deploying/ :
"While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well. Some of the options available for properly running Flask in production are documented here."
It seems that uwsgi is capable of doing almost anything I am using nginx for: serving static content, execute PHP scripts, host python web apps, ...
So (in order to simplify my environment) can I replace nginx + uwsgi with uwsgi without loss of performance/functionality?
As they say in the documentation:
Can I use uWSGI’s HTTP capabilities in production?
If you need a load balancer/proxy it can be a very good idea. It will
automatically find new uWSGI instances and can load balance in various
ways. If you want to use it as a real webserver you should take into
account that serving static files in uWSGI instances is possible, but
not as good as using a dedicated full-featured web server. If you host
static assets in the cloud or on a CDN, using uWSGI’s HTTP
capabilities you can definitely avoid configuring a full webserver.
So yes, uWSGI is slower than a traditional web server.
Besides performance, in a really basic application you're right, uWSGI can do everything the webserver offers. However, should your application grow/change over time you may find that there are many things the traditional webserver offers which uWSGI does not.
I would recommend setting up deploy scripts in your language of choice (such as Fabric for Python). I would say my webserver is one of the simplest components to deploy & setup in our applications stack, and the least "needy" - it is rarely on my radar unless I'm configuring a new server.
I'm new to linux development. I'm a bit confused on the documentation i read.
My ultimate goal is to host a simple python backed web service that would examine an incoming payload, and forward it to other server. This should be less than 30 lines of code in python.
I'm planning to use nginx to serve up python file. From my research, i also need a python web framework. I chose to go with uwsgi. I'm so confused. which one do I need? an nginx uwsgi module, or uwsgi server? i don't want to put django just for this simple purpose.
the nginx documentation mention that
Do not confuse the uwsgi protocol with the uWSGI server (that speaks the uwsgi protocol)
So, does that mean, i don't need to install uwsgi server separately? do i just install nginx, and start configuring? I'm using nginx 1.4.4
Could someone share a step by step configuration procedure on how to configure uwsgi with nginx, along with a sample python code(hello world maybe)? i can configure nginx just fine, but i don't know how to make it serve python pages. all the docs i could find involves having django on top.
You're mixing up things, so let me clarify.
Python's standard way of publishing applications via web servers is WSGI--you can think of it as a Python's native CGI. uWSGI is a WSGI-compliant server that uses uwsgi protocol to talk to other uWSGI instances or upstream servers. Usually the upstream server is nginx with HttpUwsgiModule that allows it to communicate using uwsgi protocol--with nginx you have additional layer of protection for your app server, load balancing and serving the static files. In most scenarios, You Should Be Using Nginx + UWSGI. To answer your question, uWSGI is installed and run separately from nginx, and they both need to be configured to communicate to each other.
Pure WSGI is pretty low-level, so you may want to use a WSGI-compliant framework. I guess the top two are Django and Flask.
For a hello world Flask setup, Serving Flask With Nginx seems to be a good article.