I'm developing a Flask app with a microservices architecture in Google App Engine's Standard Environment. This app will need to sustain bursts of intense traffic, so it seems perfect for the Standard Environment. My question is this:
In other environments I've used (Heroku, App Engine Flexible), you must configure your Flask app to use a production-quality WSGI web server like gunicorn, as the built-in Flask server is only suitable for development. There is documentation on this for the Flexible Environment, but not for Standard. Am I correct in assuming that this is because the Standard Environment (as configured in app.yaml) manages the request handling and everything else that gunicorn would in a production-ready way? Could it really be that easy?
Yes, it really is that easy. As a PaaS, GAE takes care of all that for you. As it did for SnapChat when it grew to 150 million users (yes, hosted on GAE).
Watch "App Engine Architecture and Services" and "You Can Run That On App Engine?". These describe some of this. Incoming requests are first captured in a queue on a GAE front-end servers. From there it decides what to do with it. If an instance of your app isn't running, it starts one and then passes the request to it. If an instance is running and not too busy, it passes the request to it immediately. If all running instances are busy, it will hold the request until an instance is able to take on another request. If the request sits in the front-end queue for too long (based on parameters you can set), GAE will start up more instances to handle the backlog.
With GAE, your app now runs in an environment with load balancers, front-end request queuing servers, edge servers, auto-scaling app servers, private global fibre networks, etc, etc. This means all the "production quality" worries that would lead you to gunicorn, etc on a self-designed server are more than handled by Google's smart engineers in GAE.
Since you're looking a microservices, you might also want to read Microservices Architecture on Google App Engine, in GAE docs.
Related
I want to determine whether if python packages can be used to implement monitoring actuator /health endpoint . Our services are deployed on to Kubernetes and logs are logged in splunk and Kubernetes is monitores using splunk observability
If you are asking about using the actuator/health endpoint for k8s readiness-probe, or are you asking if there's an admin tool written in python that can monitor your application via the Pyctuator API.
Will try to answer both:
Pyctuator is adding APIs to your Flask app (and other popular frameworks). These APIs are providing many details about your application in a way that's compatible with Codecentric's "Spring Boot Admin". I'm not familiar with other admin-tools that can consume the actuator/pyctuator API. Also, Spring Boot Admin is great for monitoring Python services that use Pyctuator.
If you are looking for endpoint for k8s readiness probe, this can be cool if you have dependencies such as DB connection that you don't want your pod to be ready until the connection is up.
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.
Here is a scenario for a system where I am trying to understand what is what:
I'm Joe, a novice programmer and I'm broke. I've got a Flask app and one physical machine. Since I'm broke, I cannot afford another machine for each piece of my system, thus the web server, application and database all live on my one machine.
I've never deployed an app before, but I know that a server can refer to a machine or software. From here on, lets call the physical machine the Rack. I've loaded an instance of MongoDB on my machine and I know that is the Database Server. In order to handle API requests, I need something on the rack that will handle HTTP/S requests, so I install and run an instance of NGINX on it and I know that this is the Web Server. However, my web server doesnt know how to run the app, so I do some research and learn about WSGI and come to find out I need another component. So I install and run an instance of Gunicorn and I know that this is the WSGI Server.
At this point I have a rack that is home to a web server to handle API calls (really just acts as a reverse proxy and pushes requests to the WSGI server), a WSGI server that serves up dynamic content from my app and a database server that stores client information used by the app.
I think I've got my head on straight, then my friend asks "Where is your Application Server?"
Is there an application server is this configuration? Do I need one?
Any basic server architecture has three layers. On one end is the web server, which fulfills requests from clients. The other end is the database server, where the data resides.
In between these two is the application server. It consists of the business logic required to interact with the web server to receive the request, and then with the database server to perform operations.
In your configuration, the WSGI serve/Flask app is the application server.
Most application servers can double up as web servers.
Reading this doc it says "You must initially deploy a version of your app to the default service before you can create and deploy subsequent services."
I don't understand this because I thought the GAE microservices were separate things as in:
But it seems this is not an accurate depiction of how GAE microservices work? Is there like a master controller "default" service that sets top level config or does some kind of routing? If I'm just running a bunch of non web apps (meaning apps that wil run on a scheduled and process data) and a frontend "app" for accepting web requests isn't necessary than why do I still need to create the default service?
The reason is that there are also several app-level configs, applicable to all services/modules:
dispatch.yaml
index.yaml
queue.yaml
cron.yaml
Some of these configs can have trouble if not deployed after/together with the default service. And some services may have dependencies on the app-level configs.
The requirement of deploying default first is simply a measure to reduce the risk of initial deployment problems. Subsequent deployments no longer have this restriction (since default is already deployed)
Yes, the default service is mandatory (sort of like a kitchen sink for all kinds of stuff, for example requests not matching any dispatch rule are sent to the default service). So just declare one of your non-web apps the default one (it doesn't matter what the default service actually does).
Somehow related (mostly for the examples): Can a default service/module in a Google App Engine app be a sibling of a non-default one in terms of folder structure?
You can deploy a default app by initializing a default AppEngine application in your project by running ./init_appengine.sh
[init_appengine.sh]
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.