Microservices Using Python Flask


Applications can be generally classified into two types: monolithic architecture and microservices architecture.

A monolithic application is a single, indivisible unit where all the functionality is contained within one codebase.

In a microservices architecture, an application is broken down into a group of loosely coupled services, called microservices. Each microservice typically has its own database and communicates with other services via well-defined APIs. They can be developed, deployed, and scaled independently.

Each microservice can be developed using different programming languages and use diverse data storage technologies.

The Amazon eCommerce application is an example of microservices architecture. In the Amazon application, different microservices are responsible for showing the product catalog, handling user authentication, processing payments, and managing your shopping cart. Each of these services can be updated or scaled without affecting the others.

Note: Whether an app is a microservice or a monolith isn’t just about how big or complex it is. It’s also about how it’s set up to be launched and grown. A small application can still be a monolith if it’s not designed to be deployed and scaled independently of other parts of the system. Similarly, a large application can be a microservice if it’s designed to be deployed and scaled independently.

In this tutorial, we will create two simple microservices using Python Flask. These microservices will communicate with each other using the HTTP protocol.

Let’s dive right in.

A Simple Example of Microservices in Python

Let’s consider a simple example where we have two microservices:

  1. Book Service: This service will manage a collection of books.
  2. Review Service: This service will manage reviews for the books.

We will create both the microservices and run the application to understand the concepts in a practical way.

Book Service

First of all, let’s create the microservice for the Book Service. Here’s the code:

from flask import Flask, jsonify, request

app = Flask(__name__)

books = [
    {"id": 1, "title": "Soft Skills", "author": "John Sonmez"},
    {"id": 2, "title": "The Daily Stoic", "author": "Ryan Holiday"}
]

@app.route('/books', methods=['GET'])
def get_books():
    return jsonify(books), 200

@app.route('/books', methods=['POST'])
def add_book():
    data = request.get_json()
    books.append(data)
    return jsonify(data), 201

app.run(port=5000, debug=True)

Note: In the above code, the numbers 200 and 201 are HTTP status codes that are used to indicate the result of a HTTP request.

HTTP Status CodeDescription
200 OKThe standard response for successful HTTP requests. When a GET request is successful, for example, the server responds with a status of 200 and the requested content.
201 CreatedThis is typically used in response to a POST request that results in creation of one more new resource(s).

These status codes are part of the HTTP protocol, and there are many more that can be used to indicate various types of responses, such as errors (4xx and 5xx), redirections (3xx), and informational messages (1xx).

Note: In this example, I used a list to store data so that it is easy for you to understand. In a real-world application, you would typically use a database to store data.

Review Service

Now, let’s create the next microservice, which is for the Review Service. Here’s the code:

from flask import Flask, jsonify, request

app = Flask(__name__)

reviews = [
    {"id": 1, "book_id": 1, "review": "Great book!"},
    {"id": 2, "book_id": 1, "review": "I loved it."},
    {"id": 3, "book_id": 2, "review": "Learned so many life lessons."}
]

@app.route('/reviews', methods=['GET'])
def get_reviews():
    return jsonify(reviews), 200

@app.route('/reviews', methods=['POST'])
def add_review():
    data = request.get_json()
    reviews.append(data)
    return jsonify(data), 201

@app.route('/reviews/<int:book_id>', methods=['GET'])
def get_reviews_for_book(book_id):
    book_reviews = [review for review in reviews if review['book_id'] == book_id]
    return jsonify(book_reviews), 200

app.run(port=5001, debug=True)

In this example, the Book Service runs on port 5000 and the Review Service runs on port 5001. Each service manages its own data and provides its own API.

The Review Service has an additional endpoint, GET /reviews/<book_id>, which returns all reviews for a specific book. This is an example of how one microservice can provide data that’s related to the data managed by another microservice.

You can run these two services simultaneously (in different terminal windows or tabs), and they will operate independently of each other. You can add books and reviews, and get lists of books and reviews, by making HTTP requests to the appropriate service.

Running the app

Now, let’s go ahead and run the application. You can run these two Python files on two different terminals or command prompts. Keep both the apps running.

Once the server is running, you can make HTTP requests to the server using a tool like curl on the command line, or using a graphical tool like Postman.

Here’s how you can make HTTP requests using curl.

Once you have both services running, you can use the following curl command on a new terminal to interact with them:

Book Service:

To get all books:

curl http://localhost:5000/books

To add a new book:

curl -X POST -H "Content-Type: application/json" -d '{"title":"Book Name", "author":"Author Name"}' http://localhost:5000/books

If you are running the POST method on Windows, you can use the following query as the Windows command prompt doesn’t support single quotes in the command.  Replace the single quotes with double quotes and escape the double quotes inside the curly braces with a backslash.

curl -X POST -H "Content-Type: application/json" -d "{\"title\":\"Book Name\", \"author\":\"Author Name\"}" http://localhost:5000/books

Review Service:

To get all reviews:

curl http://localhost:5001/reviews

To add a new review for a book:

curl -X POST -H "Content-Type: application/json" -d '{"book_id":1, "review":"Review Text"}' http://localhost:5001/reviews

To get all reviews for a specific book:

curl http://localhost:5001/reviews/1

Remember to replace “Book Name”, “Author Name”, and “Review Text” with the title, author, and review you want to add, and replace 1 with the ID of the book you want to get reviews for.

Also, note that the book ID is required when adding a review. Make sure to add the book first and use its ID when adding a review.

Note: In this example, the Review Service is dependent on the Book Service. In a real-world application, it is desirable to have each service operate independently, without direct dependencies on other services. To avoid this tight coupling, many systems use mechanisms like message queues or event streams

Final Thoughts

In this article, we have seen how microservices work with an example using Python Flask. This is a very basic example, but I hope it will give you an idea of how microservices can work together in a larger system.

Also note that in this tutorial, we are running the services on the same machine for simplicity. In a real-world application, each microservice would typically run in its own container or server, and you would use a service discovery mechanism to allow the services to find each other.

I hope this article was helpful. Share your thoughts in the comments.

Happy coding!

Ashwin Joy

I'm the face behind Pythonista Planet. I learned my first programming language back in 2015. Ever since then, I've been learning programming and immersing myself in technology. On this site, I share everything that I've learned about computer programming.

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts