Developing Backend REST API using Flask + ngnix + wsgi + load balancing and Docker | Best practices
Hello! I’m Soumil Nitin Shah, a Software and Hardware Developer based in New York City. I have completed by Bachelor in Electronic Engineering and my Double master’s in Computer and Electrical Engineering. I Develop Python Based Cross Platform Desktop Application , Web pages , Software, REST API, Database and much more I have more than 2 Years of Experience in Python.
In this Blog i will share the Best Architecture that one should be using while designing REST API. we will be using following technology
- Ngnix
- wsgi
- Docker
- Flask restful
Docker Overview
Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker’s methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.
Learn Docker basics in 25 Minutes
Lets see the Architecture for REST API
Figure 1 shows the Architecture for REST API. in this instead of exposing the REST API directly to the client we are using ngnix server which serves the requests at port 80. we are using wsgi which will create multiple instance of your Flask API and host it on different Port.it will create instance of your API on Port X ... Port Y
load balancing will make sure to route the traffic to the necessary Port based on round robin algorithms
What is Round Robin Algorithms ?
Round-robin (RR) is one of the algorithms employed by process and network schedulers in computing.[1][2] As the term is generally used, time slices (also known as time quanta)[3] are assigned to each process in equal portions and in circular order, handling all processes without priority (also known as cyclic executive). Round-robin scheduling is simple, easy to implement, and starvation-free. Round-robin scheduling can also be applied to other scheduling problems, such as data packet scheduling in computer networks. It is an operating system concept.
Lets us see the code Structure
Following is project Structure
flask folder ---->
create a file app.ini
[uwsgi] wsgi-file = run.py callable = app socket = :8080 processes = 4 threads = 2 master = true chmod-socket = 660 vacuum = true die-on-term = true
Docker File
from alpine:latest RUN apk add --no-cache python3-dev \ && pip3 install --upgrade pip WORKDIR /app COPY . /app RUN set -e; \ apk add --no-cache --virtual .build-deps \ gcc \ libc-dev \ linux-headers \ ; \ pip3 --no-cache-dir install -r requirements.txt; \ apk del .build-deps; # run the command to start uWSGI
requirement.txt
beautifulsoup4==4.8.2 boto3==1.11.2 botocore==1.14.2 bs4==0.0.1 elasticsearch==7.1.0 elasticsearch-dsl==7.1.0 flasgger==0.9.4 Flask==1.1.1 Flask-HTTPAuth==3.3.0 Flask-RESTful==0.3.7 flask-restful-swagger==0.20.1 Flask-Track-Usage==2.0.0 Flask-WTF==0.14.2 idna==2.8 itsdangerous==1.1.0 Jinja2==2.10.3 requests==2.22.0 soupsieve==1.9.5 sqlparse==0.3.0 tika==1.23.1 urllib3==1.25.7 Werkzeug==0.16.0 WTForms==2.2.1 xlrd==1.2.0 uwsgi==2.0.14
run.py
from flask import Flask from flask_restful import Resource, Api import sys import os app = Flask(__name__) api = Api(app) port = 5000 if sys.argv.__len__() > 1: port = sys.argv[1] print("You said port is : {} ".format(port)) class HelloWorld(Resource): def get(self): return {'hello': 'world Port : {} '.format(port)} api.add_resource(HelloWorld, '/fo') if __name__ == '__main__': app.run(host="0.0.0.0", port=port)
Lets create a ngnix Folder
Docker File
FROM nginx # Remove the default nginx.conf RUN rm /etc/nginx/conf.d/default.conf # Replace with our own nginx.conf COPY nginx.conf /etc/nginx/conf.d/
nginx.conf
server { listen 80; location / { include uwsgi_params; uwsgi_pass flask:8080; } }
Finally Docker-compose.yml
version: "3.7" services: flask: build: ./flask container_name: flask restart: always environment: - APP_NAME=MyFlaskApp expose: - 8080 nginx: build: ./nginx container_name: nginx restart: always ports: - "80:80"
Video
Senior Software Engineer L3 at Wayfair
3 年please provide a GitHub repo for this