Microservice architecture

Microservice architecture is an architectural style of developing a single application as a suite of small independent services, each running in its own process and communicating via lightweight mechanisms—typically, using HTTP protocol.

Microservices are independently deployable components, and usually have zero or minimalistic central management or configuration.

Microservices can be thought of as a specific implementation style for Service Oriented Architectures (SOA), where, instead of building a monolith application top-down, the application is built as a dynamic group of mutually interacting, independent services.

Traditionally, enterprise applications were built in a monolithic pattern, typically consisting of these three layers:

  1. A client-side user interface (UI) layer consisting of HTML and JavaScript.
  2. A server-side application consisting of the business logic.
  3. A database and data access layer, which holds the business data.

On the other hand, a microservices architecture will split this layer into multiple services. For example, the business logic, instead of being in a single application, will be split into multiple component services, whose interactions define the logic flow inside the application. The services might query a single database or independent local databases, with the latter configuration being more common.

Data in microservices architectures are usually processed and returned in the form of document objects—typically encoded in JSON.

The following schematic diagram illustrates the difference of a monolithic architecture from a microservices one:

Microservice architecture

Monolithic (left) versus microservices (right) Architecture

Microservice frameworks in Python

With microservices being more of a philosophy or style of architecture, there are no distinct classes of software frameworks that one can say is the right fit for them. However, one can still make a few educated projections for the properties that a framework should have for it being a good choice for building a microservices architecture for your web application in Python. These properties include the following:

  • The component architecture should be flexible. The framework should not be rigid in the component choices that it stipulates to make the different parts of the system work.
  • The core of the framework should be lightweight. This makes sense, since if we start off with, say, a lot of dependencies for the microservices framework itself, the software starts feeling heavy right in the beginning. This may cause issues in deployment, testing, and so on.
  • The framework should support zero or minimalistic configuration. Microservices architectures are usually configured automatically (zero configuration) or with a minimal set of configuration inputs that are available at one place. Usually the configuration is itself available as a microservice for other services to query and make the sharing of configuration easy, consistent, and scalable.
  • It should make it very easy to take an existing piece of business logic, say, coded as a class or a function, and turn it into an HTTP or RCP service. This allows reuse and smart refactoring of code.

If you use these principles and look around in the Python software ecosystem, you will figure out that a few web application frameworks fit the bill, whereas a few don't.

For example, Flask and its single-file counterpart Bottle are good candidates for a microservices framework due to their minimal footprint, small core, and simple configuration.

A framework such as Pyramid can also be used for a microservices architecture since it promotes flexibility of choice of components and eschews tight integration.

A more sophisticated web framework such as Django makes a poor choice for a microservices framework due to exactly the opposite reasons–tight vertical integration of components, lack of flexibility in choosing components, complex configuration, and so on.

Another framework that is written specifically for implementing microservices in Python is Nameko. Nameko is geared toward testability of the application, and it provides support for different protocols for communication such as HTTP, RPC (over AMQP)—a Pub-Sub system, and a Timer service.

We will not be going into details of these frameworks. On the other hand, we will take a look at architecting and designing a real-life example of a web application using microservices.

Microservices example – restaurant reservation

Let's take a real-life example for a Python web application, and try to design it as a set of microservices.

Our application is a restaurant reservation app that helps users make a reservation for a certain number of people at a specific time in a restaurant close to their current location. Assume that reservations are only done for the same day.

The application needs to do the following:

  1. Return a list of restaurants open for business at the time for which the user wants to make the reservation.
  2. For a given restaurant, return enough meta information, such as cuisine choices, rating, pricing, and so on, and allow the user to filter the restaurants based on their criteria.
  3. Once the user has made a choice, allow them to make a reservation at the selected restaurant for a certain number of people for a given time.

Each of these requirements is granular enough to have its own microservice.

Hence, our application will be designed with the following set of microservices:

  • A service that uses the user's location, and returns a list of restaurants that are open for business and that support the online reservation API.
  • A second service that retrieves metadata for a given hotel, given the restaurant ID. The application can use this metadata to compare against the user's criteria to see if it's a match.
  • A third service, which, given a restaurant ID, the user's information, the number of seats required, and the time of reservation, uses the reservation API to make a reservation for seats, and returns the status.

The core parts of the application logic now fit these three microservices. Once they are implemented, the plumbing—in terms of calling these services and performing a reservation—will happen in the application logic directly.

We will not be showing any code for this application as that is a project on its own, but we will show the reader how the microservices look like in terms of their APIs and return data:

Microservices example – restaurant reservation

Architecture of restaurant reservation application using microservices

A microservice usually returns data in the form of JSON. For example, our first service, which returns a list of restaurants, would return a JSON similar to the one that follows:

GET /restaurants?geohash=tdr1y1g1zgzc

{
    "8f95e6ad-17a7-48a9-9f82-07972d2bc660": {
        "name": "Tandoor",
        "address": "Centenary building, #28, MG Road b-01"
        "hours": "12.00 – 23.30"
	},
  "4307a4b1-6f35-481b-915b-c57d2d625e93": {
        "name": "Karavalli",
        "address": "The Gateway Hotel, 66, Ground Floor"
        "hours": "12.30 – 01:00"
	},
   ...
} 

The second service, which returns restaurant metadata, would mostly return a JSON like this one:

GET /restaurants/8f95e6ad-17a7-48a9-9f82-07972d2bc660

{
    
   "name": "Tandoor",
   "address": "Centenary building, #28, MG Road b-01"
   "hours": "12.00 – 23.30",
   "rating": 4.5,
   "cuisine": "north indian",
   "lunch buffet": "no",
   "dinner buffet": "no",
   "price": 800
   
} 

Next is the interaction for the third one, which does a booking given the restaurant ID.

Since this service needs the user to provide information for the reservation, it needs a JSON payload with the details of booking. Hence, this is best done as an HTTP POST call:

POST  /restaurants/reserve

The service in this case will use the following given payload as the POST data:

{
   "name": "Anand B Pillai",
   "phone": 9880078014,
   "time": "2017-04-14 20:40:00",
   "seats": 3,
   "id": "8f95e6ad-17a7-48a9-9f82-07972d2bc660"
} 

It will return a JSON like the following as a response:

{
   "status": "confirmed",
   "code": "WJ7D2B",
   "time": "2017-04-14 20:40:00",
   "seats": 3
}

With this design in place, it is not very difficult to implement the application in a framework of your choice, be it Flask, Bottle, Nameko, or anything else.

Microservices – advantages

So what are the advantages of using microservices over a monolithic application? Let's take a look at some of the important ones:

  • Microservices enhance separation of concern by splitting the application logic into multiple services. This improves cohesion, and decreases coupling. There is no need for a top-down, upfront design of the system, since the business logic is not in a single place. Instead, the architect can focus on the interplay and communication between the microservices and the application, and let the design and architecture of the microservices itself emerge iteratively through refactoring.
  • Microservices improve testability, since now each part of the logic is independently testable as a separate service, and hence is easy to isolate from other parts and test.
  • Teams can be organized around the business capabilities rather than around tiers of the application or technology layers. Since each microservice includes logic, data, and deployment, companies using microservices encourage cross-functional roles. This helps to build a more agile organization.
  • Microservices encourage decentralized data. Usually, each service will have its own local database or data store instead of the central database that is preferred by monolithic applications.
  • Microservices facilitate continuous delivery and integration, and fast deployments. Since a change to business logic might often need only a small change in one or a few services, testing and redeployment can be often done in tight cycles, and in most cases, can be fully automated.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.141.219