Concurrent nested requests in a microservices environment built with Django - python

I'm developing a microservices architecture with Django in which services communicate each other through RESTful APIs.
A request coming from a client is served by a service, which then requires to make a new (nested) HTTP request to another service as it is shown in the picture below, in order to mantain decoupling between services.
In this scenario, it may happen that two different requests are fired by the client and served simultaneously by the first service. Then, one of the two nested requests to the second service remains unserved until a 503 error (Service Unavailable) occurs.
It seems that concurrency between nested requests is bad handled by the server.
RESTful APIs are implemented with Django REST framework and nested requests are made with the Python requests library. Here is an example:
from rest_framework.views import APIView
import requests
class FirstServiceView(APIView):
def get(self, request, format=None):
# Code...
# The nested requests to the second service
response = requests.get("http://127.0.0.1:8000/second_service/")
# Other code...
It's worth noting that this behaviour happens with both the development server of Django and Apache. Furthermore, no concurrency on the database is involved in this case.

Related

How to connect a Flask Back-end app to Flask Front-end app?

I've developed a Python Flask Back-end app which allows me to do some HTTP requests on a Jsonfile (a sort of database) such as GET (to see a list of items) or POST (to create a new item in the Json database). Until now, I used Postman to test my app and all worked well. However, I'd like to develop a Python Flask Front-end app in order to create a graphical interface (in a web browser with jinja templates) to do the same requests. The problem is, I don't know how to begin my new app, I've googled all my questions but found no answer...
How can we "link" front-end and back-end apps in order to get the information from the web brower, make the requests via the back-end and then send the response with the front-end?
Using RESTful API.
A infrastructure solution could be (a classic one):
Your app server listening on 5000. It uses the REST architectural.
Your frontend server listening on 80/443. It makes requests to your app server to get the data and fill your html template with this data. The requests can be made with a library like requests. The requests library is one of the simpliest but you can choose another one to make HTTP requests.
Workflow:
Client <-HTTP requests-> Frontend <-HTTP requests made with requests->
App Server <--> Database
Advantage:
One of the advantage of this architecture: you can easily duplicate your servers or having multiple app servers responsible of different tasks. They can be running on the same machine or separated machines.
Serving static files:
If you are talking about serving static files for the frontend, then you should use an existing Webserver like Nginx (html/css/js files).

is "from flask import request" identical to "import requests"?

In other words, is the flask request class identical to the requests library?
I consulted:
http://flask.pocoo.org/docs/0.11/api/
http://docs.python-requests.org/en/master/
but cannot tell for sure. I see code examples where people seem to use them interchangeably.
No these are not only completely different libraries, but completely different purposes.
Flask is a web framework which clients make requests to. The Flask request object contains the data that the client (eg a browser) has sent to your app - ie the URL parameters, any POST data, etc.
The requests library is for your app to make HTTP request to other sites, usually APIs. It makes an outgoing request and returns the response from the external site.

Separate initialization for each worker in Flask+Gunicorn

Design:-
My flask application views contact an API endpoint during the lifetime of requests. Each of these API requests require a token. Due to the server side limitation, I can't have two threads using the same token for initiating requests.
Requirement:-
To contact this API, I need to fetch an API token. I would like to do this once per worker and then share that value among views. (just a read-only variable).
I want each "worker" that serves requests to have a separate "token". How can that be achieved in Flask?
I don't want to issue a fresh token each time a request is served as that'll be horribly slow.

Best practices to combine REST API with web interface using FLASK

I currently build a web application using flask, sqlalchemy and jinja2.
To get a proper web interface, I build my views as follows:
#app.route('/mydata/', methods=['GET'])
#login_required
def mydata_list():
# build data here...
return render_template('mydata/index.html', data=data))
Now, if I need to build a REST API, I am supposed to terminate with
return jsonify(data)
So, how to handle this to avoid code duplication? Is it a good practice to add a ?api=True to my url, test it in my view, then return appropriate answer?
There is really no right or wrong way to do this, more so with Flask, which is a framework that imposes so few rules on the developer.
If you want my opinion, I think using the same set of view functions for web site and API leads to code that is harder to maintain, because there are a few significant differences between the two, for example:
Authentication: this is typically done in very different ways for web vs. API.
Content: for the API you just return data, but for a web page the view function may need to do more work and obtain extra data that is only needed for rendering the template.
Request methods: APIs use more HTTP request methods than web apps. For example, to delete a resource through an API the client normally sends a DELETE request. A web application running on a web browser needs to do everything with GET and POST requests. Also, the POST request method has different usages in APIs vs. web apps.
My recommendation is that you make your view functions for both APIs and web apps very thin and put the business logic of your application in common classes that both sets of view functions can invoke.
If you want to use the same endpoint for serving a template as well as JSON data, you can test whether this is an AJAX request with request.is_xhr. For example:
#app.route('/numbers/')
def numbers():
data = [1, 2, 3]
if request.is_xhr:
return jsonify(data=data)
return render_template('numbers.html', data=data)

How can I share a dict between two different http requests

The Django application loads data from a file to a Python dict, process it and sends it as http response. Now say n number of request are received on the web server then this Django app would run n times and load data from a file to a Python dict n times. I was wondering if somehow I can make this data being loaded to the dict only once while n http response could be served.
An example view.py file for the problem situation can be as followed:
from django.http import HttpResponse
from django.http import HttpRequest
def hello(request):
data = open("abc").readlines()
return HttpResponse(data[0])
Binding the dictionary to a global name will make it persist for as long as the Django project runs. Note that each Django process (some WSGI containers, e.g. mod_wsgi, can run multiple processes for an app) will have its own independent copy of the dictionary.
If the data is relevant to the user, you can use djanog's session framework to persist data across requests. If the data needs to be shared between numerous users, you can use the cache.
This is a job for the Django Middleware. Add it to your settings and it will persist across your request. Its a better option then persistence and definitely a lot better than using a global object.
Middleware is a framework of hooks into Django’s request/response processing. It’s a light, low-level “plugin” system for globally altering Django’s input and/or output. Each middleware component is responsible for doing some specific function. For example, Django includes a middleware component, XViewMiddleware, that adds an "X-View" HTTP header to every response to a HEAD request.

Categories

Resources