Microservices. Development and refactoring patterns with Java examples

Original author: Ben Nadel
  • Transfer
Hi, Habr!

We are starting to translate Chris Richardson's book " Microservices Patterns. With examples in Java ". Before the premiere in Russian for another six months, but we would like to offer you a kind of trailer - a slightly abbreviated review of this book from Ben Nadel (Ben Nadel), who read the MEAP version. The review actively quoted text from the Kindle-version of Richardson.

Welcome under the cut!

I found out about Chris Richardson when I got acquainted with his Internet resource Microservices.io . Where, to be honest, a staggering amount of information is given - which I decided to postpone until later, because by that moment I did not know how to approach it, especially considering that I had practically no business with microservices. I like to read more. Therefore, having learned that Chris has the author’s book Microservices Patterns: With Examples In Java , I was simply inspired. So much so that he could not wait for her release. So I purchased and read the “early version” (MEAP) from Manning. Last week I only did that I studied this book, and I think that this is a fascinating, pragmatic and holistic study of the microservice approach to development.

The whole book is built in the form of the story of Mary - CTO (Chief Technical Officer) of Food To Go, Inc (FTGO). The company seeks to develop the business by launching the refactoring of its old monolithic application and converting it into microservice architecture. Mary takes on this project, because the development speed has decreased, and the bosses are more and more irritated by the fact that programmers under Mary’s control are not able to issue new features in a sufficiently high-quality form.

Of course, the main problem of Mary is the so-called "monolithic hell" in Richardson's terminology. While the monolith is a large and expanding application, Richardson focuses on the rather subtle aspect of the FTGO migration so that it is more convenient to explain and convey all the concepts. In this case, the content of the book is incredibly digestible. Most architecture considerations are usually either overly simplistic or over complicated. However, Richardson managed to find a middle ground by constructing a model of the subject area, which (almost) fits in the head, but it is difficult enough to illustrate interesting inter-service task flows.

From the very beginning, I anticipated that Richardson would be pragmatic in all details. Not a single aspect in the book is presented as a “silver bullet” or “the only solution”. Everywhere we see a calculated choice, a set of well-defined compromises. For example, the author submits even the very idea of ​​microservices in this way: microservice architecture should always be avoided, unless it is absolutely necessary:
Another challenge associated with the use of microservice architecture is to decide at what point in the life cycle of an application to start using this architecture. When developing the first version of an application, you often still do not encounter problems that such an architecture solves. Moreover, using a verified distributed architecture will only slow down development. Such a dilemma can arise in startups, where the most important challenge is usually the rapid development of a business model and its own application. When using microservice architecture it is much more difficult to organize fast iterations. The development of a startup should definitely begin with a monolithic application. (Kindle-version, address 416)
Richardson also considers microservices in a holistic perspective, talking about the dynamics of the team’s work as a completely independent circle of problems that builds on the technological part. Of course, he considers such topics as Conway’s Law and Conway ’s Reverse Maneuver, but at the same time, he also touches on the fact that programmers are emotional, pathetic characters to whom you must “sell” the idea of ​​microservices:
Turning to the microservice paradigm, you are forced to change your architecture, your organization and development processes. However, in the end, the working environment is changing, the conditions in which people work, and people, as already mentioned, are emotional. If human emotions are ignored, the introduction of microservices in an organization can turn into a steep route. (Kindle-version, address 718)
The strategies described by the author relate to the entire business, affecting managers and managers who may not dare to embark on a great refactoring, taking away from him valuable resources, people who could actively develop new features:
The essential advantage of step-by-step refactoring in the direction of microservice architecture is that such a strategy starts to pay off immediately. This is not at all the situation that with the "overhaul" of the code, which will not bring any benefit to complete ...

Another advantage of the situation in which the value of the transition is acquired at an early stage - we can attract business support to ensure migration. Such current support is fundamental, since the more active the refactoring is, the less time it will be possible to spend on developing features. In some organizations, it is difficult to get rid of technical debt, since previous attempts could be overly ambitious and did not bring the desired benefits. As a result, the business is reluctant to continue investing in “putting things in order”. The step-by-step nature of refactoring in the case of microservices means that a team can demonstrate valuable results very often. (Kindle-version address 10769)
From the technological point of view in the book “Microservices. Development and refactoring patterns ”covers a wide range of topics: from hexagonal architectures, testing and continuous integration to messaging patterns and creating observable systems. Such coverage implies that some of the topics in the book are covered in more detail by others. However, again, Richardson is perfectly able to balance everything and give just enough details so that you can substantively discuss the topic without discouraging the reader.

In fact, the content of the book is organized in such a way that you yourself can choose which topics to go into. Each chapter before a detailed immersion in the subject is given a list of TL; DR, which briefly lists the pros and cons. Thus, you manage to catch the most important moments of the chapter, without reading every word.

To be honest, I just went through two chapters on testing microservices and one chapter on deploying microservices. I am sure that the author has worked on these topics perfectly, but it seemed to me that there simply is more information than I can digest. Deployment is not an urgent daily task for me. I've written several tests in my life.
Thus, I wanted to leave enough space in my unclouded cave mind to put material from all the other chapters there: on subject-oriented design (DDD), interprocess communication, and data synchronization.

One of the sections that made a particularly strong impression on me tells us which service should handle requests of one specialized type, namely, to find suitable restaurants near the current location of the user:
However, it is difficult to implement even such requests that are local from the point of view of a particular service. This is possible for several reasons. Firstly, because (as described below), sometimes it is not advisable to implement a request in the service that owns the data. Another reason is that sometimes the service database (or data model) cannot effectively support the request (Kindle version, address 5659)
... If in the FTGO application information about restaurants is stored in [some other] database, then the implementation of the request is findAvailableRestaurant()much more complicated. A replica of restaurant data should be kept in a form that allows geospatial queries to be supported. For example, an application could use a Geospatial Indexing Library for DynamoDB, where the table is used as a geospatial index. Alternatively, the application can store a replica of restaurant data in a completely different type of database. A similar situation occurs when we use text queries with a database for text search. (Kindle-version, address 5675)
... In this case, it is advisable (at least at first glance) that the query operation is implemented by the service that owns the data. However, in addition to data ownership, other factors have to be taken into account.

You also need to take into account the need for segregation of duties and avoid overloading services with too many features. For example, the main responsibility of the team developing the Restaurant service is to help restaurant managers to serve the work of the establishment. This task is not at all of the plan that the implementation of a critical query for working with large amounts of data. Moreover, if the development team were in charge of the operation findAvailableRestaurants(), they would constantly be afraid to introduce such changes that could prevent consumers from placing orders. (Kindle-version, address 5675)
Here, my brain was blown up a little, because for the first time I saw a service, whose only function was to optimize data from another service for a specific task. However, as Richardson points out, this is just a more generalized abstraction of the very idea that underlies full-text search, for example, in Apache Lucene (this tool provides full-text indexing on top of another data store).

I suspect - or rather, I want to hope - that, having seen such a division of duties, the reader will begin to draw a completely new boundary between services. He will not only think about “data ownership”, but will also start to take into account “business opportunities” - that is, the factor of real value, so that the database does not seem just to be the place where the state is stored.

Another aspect emphasized in the discussion of this topic is the absolute importance of data synchronization and replication, as well as asynchronous messaging in the microservice architecture. This topic runs through the entire book of Richardson, no matter what they say: the creation of microservice from scratch or the gradual refactoring of the monolith into microservices (a separate chapter is devoted to this topic). He makes it quite clear that synchronization is the backbone force that really allows to embody many things.

I could mention a lot of interesting things. What is it worth, for example, the fact that Richardson talks about authentication and authorization in a distributed system in a proper way? I think this topic has not yet been fully investigated, to put it mildly. The author explains the subject-oriented design in the most accessible way. It also demonstrates that even very simple classes can have a behavior.

For more than a year now I have been trying to properly understand the architecture of distributed systems and microservice patterns (which is especially difficult, since my daily work is related to the maintenance of the monolith). Many of the texts that I read on these topics are either excessively superficial, or too narrow and at the same time in-depth. The book “Microservices. Patterns of development and refactoring "really is the golden mean between these two extremes. I strongly recommend this book to everyone (bold ours) who are trying (including, so far without success) to move from a monolithic architecture to a distributed system.

Also popular now: