Hands-On Docker for Microservices with Python
上QQ阅读APP看书,第一时间看更新

Analyzing the current system

The very first step, as we defined before, to migrate from a monolith to a collection of microservices is understanding the current system. This stage should not be underestimated. It is highly likely that no single person has a good understanding of the different components of the monolith, especially if some parts are legacy.

The objective of this phase is to determine whether a change to microservices will actually be beneficial and to get an initial idea of what microservices will be the result of the migration. As we have discussed, making the move is a big investment and should not be taken lightly. Making a detailed estimation of the effort required won't be possible at this stage; uncertainty will be big at this point, but a thousand-mile journey starts with a single step.

The effort involved will vastly depend on how structured the monolith is. This may vary from a mess of spaghetti code that has grown organically without much direction, to a well-structured and modularized code base.

We will use an example application in this book—a micro-blogging site called MyThoughts, a simple service that will allow us to post and read short messages or thoughts. The website allows us to log in, post a new thought, see our thoughts, and search for thoughts in the system. 

As a first step, we will draw an architectural diagram of the monolith. Reduce the current system to a list of blocks that interact with each other.

The code for our example is available here: https://github.com/PacktPublishing/Hands-On-Docker-for-Microservices-with-Python/tree/master/Chapter01/Monolith. It is a Django application that uses Bootstrap for its HTML interface. See the README for instructions on how to run it.

In our example, the MyThoughts model is described in the following diagram:

As you can see, the monolith seems to be following a Model View Controller structure (https://www.codecademy.com/articles/mvc):

Django uses a structure called Model Template View, which follows a similar pattern to the MVC one. Read the article at https://medium.com/shecodeafrica/understanding-the-mvc-pattern-in-django-edda05b9f43f for more information. Whether it's 100% MCV or not is debatable. Let's not get stuck on semantics, but use the definition as a starting point to describe the system.
  • There are three entities stored in a database and accessed through the models: the user, the thoughts, and the session models. The session is used for keeping track of logins.
  • A user can log in and out to access the site through the code in login.py. If the user logs in, a session is created that allows the user to see the rest of the website.
Please note that the handling of authentication and passwords in this example is for demonstration purposes only. Use the default mechanisms in Django for more secure access. It's the same for the session, where the native session management is not used.
  • A user can see their own thoughts. On the same page, there's a new form that creates a new thought. This is handled by the thoughts.py file, which retrieves and stores the thoughts through ThoughtModel.
  • To search other users' thoughts, there's a search bar that connects to the search.py module and returns the obtained values.
  • The HTML is rendered through the login.html, search.html, list_thoughts.html, and base.html templates.
  • On top of that, there are static assets that style the website.

This example is very simple, but we are able to see some of the interdependencies:

  • The static data is very isolated. It can be changed at any point without requiring any changes anywhere else (as long as the templates are compatible with Bootstrap).
  • The search functionality is strongly related to list down thoughts. The template is similar, and the information is displayed in the same way.
  • Login and logout don't interact with ThoughtModel. They edit the session, but the rest of the application only reads the information there.
  • The base.html template generates the top bar and it's used for all pages.

After this analysis, some ideas on how to proceed come to mind:

  1. Just leave it the way it is, investing in structuring it, but without splitting it into several services. It has a certain structure already, though some parts could be improved. For example, the handling of whether the user is logged in or not could be better. This is obviously a small example, and, in real life, splitting it into microservices would have a big overhead. Remember that sticking with a monolith may be a viable strategy, but if you do, please invest time in cleaning up code and paying technical debt.
  1. Searching for thoughts is pretty basic. At the moment, we directly search the database. If there are millions of thoughts, this won't be a viable option. The code in search.py could call a specific search microservice, backed by a search engine such as Solr (https://lucene.apache.org/solr/) or Elasticsearch (https://www.elastic.co/products/elasticsearch). This will scale the searches and could add capabilities like searching between dates or displaying the text matches. Search is also read-only, so it may be a good idea to detach calls creating new thoughts from calls searching them.
  2. Authentication is also a different problem from reading and writing thoughts. Splitting it will allow us to keep on track for new security issues and have a team specifically dealing with those issues. From the point of view of the rest of the application, it only requires you to have something available to check whether a user is logged or not, and that can be delegated in a module or package.
  3. The frontend is pretty static at the moment. Maybe we want to create a single-page application that calls a backend API to render the frontend in the client. To do that, a RESTful API microservice that is able to return elements for thoughts and searches will need to be created. The frontend could be coded in a JavaScript framework, such as Angular (https://angular.io) or React (https://reactjs.org/). In this case, the new microservice will be the frontend, which will be served as static, precompiled code, and will pull from the backend.
  4. The RESTful API backend will also be available to allow external developers to create their own tools on top of the MyThoughts data, for example, to create a native phone app.

These are just some ideas, which will need to be discussed and evaluated. What are the specific pain points for your monolithic app? What is the roadmap and the strategic future? What are the most important points and features for the present or the future? Maybe, for one company, having strong security is a priority, and point 3 is critical, but for another, point 5 might be part of the expansion model to work with partners.

The team's structure is also important. Point 4 will require a team with good frontend and JavaScript skills, while point 2 may involve backend optimization and database work to allow an efficient search of millions of records.

Do not jump too quickly to conclusions here; think about what capacity is viable and what your teams can achieve. As we discussed before, the change to microservices requires a certain way of working. Check with the people involved for their feedback and suggestions.

After some consideration, for our example, we propose the following potential architecture:

The system will be divided into the following modules:

  1. Users backend: This will have the responsibility for all authentication tasks and keep information about the users. It will store its data in the database.
  2. Thoughts backend: This will create and store thoughts
  3. Search backend: This will allow searching thoughts.
  4. A proxy that will route any request to the proper backend. This needs to be externally accessible.
  5. HTML frontend: This will replicate the current functionality. This will ensure that we work in a backward-compatible way and that the transition can be made smoothly.
  6. Allowing clients to access the backends will allow the creation of other clients than our HTML frontend. A dynamic frontend server will be created, and there are talks with an external company to create a mobile app.
  7. Static assets: A web server capable of handling static files. This will serve the styling for the HTML frontend and the index files and JavaScript files for the dynamic frontend.

This architecture will need to adapt to real-life usage; to validate it, we'll need to measure the existing usage.