Chapter 4. Reasons for Using Microservices

Microservices offer many benefits, and these are discussed in this chapter. A detailed understanding of the benefits enables a better evaluation of whether microservices represent a sensible approach in a given use case. The chapter continues the discussion from section 1.2 and explains the benefits in more detail.

Section 4.1 explains the technical benefits of microservices. However, microservices also influence the organization. This is described in section 4.2. Finally, section 4.3 addresses the benefits from a business perspective.

4.1 Technical Benefits

Microservices are an effective modularization technique. Calling one microservice from another requires the developer to consciously create code that communicates over the network. This does not happen by accident; a developer has to make that happen within the communication infrastructure. Consequently, dependencies between microservices do not creep in unintentionally; a developer has to generate them explicitly. Without microservices, it is easy for a developer to just use another class and unwittingly create a dependency that was not architecturally intended.

Let us assume, for instance, that in an e-commerce application the product search should be able to call the order process, but not the other way round. This ensures that the product search can be changed without influencing the order process, as the product search does not use the order process. Now a dependency between the product search and the order process is introduced, for example, because developers found a piece of functionality there that was useful for them. Consequently, the product search and order processes now depend on each other and can only be changed together.

Once undesired dependencies have started to creep into the system, additional dependencies rapidly accrue. The application architecture erodes. This erosion can normally only be prevented with the use of architecture management tools. Such tools have a model of the desired architecture and can discover when a developer has introduced an undesired dependency. The developer can then immediately remove the dependency before any harm is done and the architecture suffers. Appropriate tools are presented in section 7.2.

In a microservices-based architecture, the product search and order processes would be separate microservices. To create a dependency, the developer would have to explicitly implement it within the communication mechanisms. This presents a relatively high barrier and consequently does not normally happen unnoticed, even without architecture management tools. This reduces the chances that the architecture erodes because of dependencies between microservices. The microservice boundaries act like firewalls, which prevent architectural erosion. Microservices offer strong modularization because it is difficult to overstep the boundaries between modules.

Replacing Microservices

Working with old software systems poses a significant challenge in that further development of the software may be difficult due to poor code quality. It is often risky to replace the software. It may be unclear exactly how the software works, and the system may be very large. The larger the software system, the more effort is required to replace it. If the software is supporting important business processes, it may be nearly impossible to change it. The failure of these business processes can have a significant negative impact, and each software change risks a failure.

Although this is a fundamental problem, most software architectures are never really aimed at replacing software. However, microservices do support this goal; they can be replaced individually, since they are separate and small deployment units. Therefore, the technical prerequisites for a replacement are better. Eventually it is not necessary to replace a large software system, but only a small microservice. Whenever necessary, additional microservices can be replaced.

With the new microservices, the developers are not tied to the old technology stack, but free to use other technologies at will. If the microservice is also independent in a domain sense, the logic is easier to understand. The developer does not need to understand the entire system, just the functionality of an individual microservice. Knowledge regarding the domain is a prerequisite for the successful replacement of a microservice.

Moreover, microservices keep functioning when another microservice fails. Even if the replacement of a microservice leads to the temporary failure of one microservice, the system as a whole can keep operating. This reduces the risk associated with a replacement.

Sustainable Software Development

Starting a new software project is simple because there is not much code, the code structure is clean, and developers can make rapid progress. Over time, however, the architecture can erode and development becomes more difficult as its complexity increases. At some point, the software turns into a legacy system. As previously discussed, microservices prevent architectural erosion. When a microservice has turned into a legacy system, it can be replaced. This means that microservices can make sustainable software development possible and that a high level of productivity can be reached over the long term. However, in a microservice-based system, it can be the case that a lot of code has to be newly written. This will, of course, decrease productivity.

Handling Legacy

Replacing microservices is only possible if the system is already implemented in a microservice-based manner. However, the replacement and amendment of existing legacy applications can be made easier with microservices, too. The legacy applications only have to provide an interface that enables the microservice to communicate with the legacy application. Comprehensive code changes or the integration of new code components into the legacy system is not necessary. This can mean that code level integration can be avoided. Otherwise such integration is a big challenge in the case of legacy systems. Amending the system is particularly easy when a microservice can intercept the processing of all calls and process them itself. Such calls can be HTTP requests for the creation of web sites or REST calls.

In this situation, the microservice can complement the legacy system. There are different ways for this to happen:

• The microservice can process certain requests by itself while leaving others to the legacy system.

• Alternatively, the microservice can change the requests and then transfer them to the actual application.

This approach is similar to the SOA approach (see Chapter 6, “Microservices and SOA”), which deals with the comprehensive integration of different applications. When the applications are split into services, these services be orchestrated anew, and it is also possible to replace individual services with microservices.

Continuous Delivery

Continuous delivery enables software to be brought into production regularly thanks to a simple, reproducible process. This is achieved via a continuous delivery pipeline (see Figure 4.2):

• In the commit phase, the software is compiled, the unit tests are run, and static code analysis might be performed.

• The automated acceptance tests in the next phase ensure that the software meets the business requirements and would be accepted by the customer.

• Capacity tests check that the software performs adequately to support the expected number of users. These tests are automated as well.

• Explorative tests, on the other hand, are performed manually and serve to test certain areas of the system such as new features or certain aspects like software security.

• Finally, the software is brought into production. Ideally, this process is also automated.

Image

Figure 4.2 Continuous Delivery Pipeline

Software moves through the individual phases consecutively. For example, a build can successfully pass the acceptance tests. However, the capacity tests reveal that the software does not meet the requirements under the expected load. In this case, the software is never promoted to the remaining phases such as explorative tests or production.

A fully automated continuous delivery pipeline is ideal. However, software needs to get into production, and it may be necessary to optimize the current process step-by-step.

Continuous delivery is particular easy to realize with microservices.1 Microservices are independent deployment units. Consequently, they can be brought into production independently of other services. This has a significant impact on the continuous delivery pipeline:

1. http://slideshare.net/ewolff/software-architecture-for-devops-andcontinuousdelivery

• The pipeline is faster as only small microservices have to be tested and brought into production at one time. This accelerates feedback. Rapid feedback is a primary goal of continuous delivery. When it takes weeks for developers to know that their code has caused a problem in production, it will be difficult to become reacquainted with the code and to analyze the problem.

• The risk of deployment decreases. The deployed units are smaller and can therefore be more easily rolled back. Also microservice-based systems are designed to be resilient to failures in individual microservices. A failure in the deployment of a single microservice shouldn’t impact the system as a whole.

• Measures to further reduce risk are easier to implement with smaller deployment units. For instance, in case of blue/green deployment, a new environment is built up with the new release. This is similar to canary releasing: in this approach, a single server is provided with the new software version. Only when this server runs successfully in production is the new version rolled out to the other servers. For a deployment monolith, this approach can be hard or nearly impossible to implement, as it requires a lot of resources for the large number of environments. With microservices, the required environments are much smaller, and the procedure is therefore easier.

• Test environments pose additional challenges. For instance, when a third-party system is used, the environment also has to contain a test version of this third-party system. With smaller deployment units, the demands on the environments are lower. The environments for microservices only have to integrate with the third-party systems that are necessary for the individual microservice. It is also possible to test the systems using mocks of the third-party systems. This helps with testing and is also an interesting method of testing microservices independently of each other.

Continuous delivery is one of the most important arguments for microservices. Many projects invest in migrating to microservices in order to facilitate the creation of a continuous delivery pipeline.

However, continuous delivery is also a prerequisite for microservices. Quickly bringing numerous microservices into production manually becomes unfeasible, and an automated approach is required. So microservices profit from continuous delivery and vice versa.2

2. http://slideshare.net/ewolff/continuous-delivery-and-micro-services-a-symbiosis

Scaling

Microservices are offered over network-reachable interfaces, which can be accessed, for instance, via HTTP or via a message solution. Each microservice can run on one server or on several. When the service runs on several servers, the load can be distributed across the different servers. It is also possible to install and run microservices on computers that perform differently. Each microservice can implement its own scaling.

In addition, caches can be placed in front of microservices. For REST-based microservices, it can be sufficient to use a generic HTTP cache. This significantly reduces the implementation effort for such a cache. The HTTP protocol contains comprehensive support for caching, which is very helpful in this context.

Furthermore, it might be possible to install microservices at different locations within the network in order to bring them closer to the caller. In the case of world-wide distributed cloud environments, it no longer matters in which computing center the microservices run. When the microservice infrastructure uses several computing centers and always processes calls in the nearest computing center, the architecture can significantly reduce the response times. Also, static content can be delivered by a CDN (content delivery network), whose servers are located even closer to the users.

However, improved scaling and support for caching cannot work miracles: micro-services result in a distributed architecture. Calls via the network are a lot slower than local calls. From a pure performance perspective, it might be better to combine several microservices or to use technologies that focus on local calls (see Chapter 14, “Technologies for Nanoservices”).

Robustness

Theoretically, a microservices-based architecture should be less reliable than other architectural approaches. Microservices are, after all, distributed systems, so there is an inherent risk of network failures adding to the usual sources of errors. Also, microservices run on several servers, increasing the likelihood of hardware failures.

To ensure high availability, a microservices-based architecture has to be correctly designed. The communication between microservices has to form a kind of firewall: The failure of a microservice should not propagate. This prevents problems from arising in an individual microservice and leading to a failure of the entire system.

To achieve this, a microservice which is calling another microservice has to somehow keep working when a failure occurs. One way to do this might be to assume some default values. Alternatively, the failure might lead to a graceful degradation such as some sort of reduced service.

How a failure is dealt with technically can be critical: the operating-system–level timeout for TCP/IP connections is often set to five minutes, for example. If, due to the failure of a microservice, requests run into this timeout, the thread is blocked for five minutes. At some point, all threads will be blocked. If that happens, the calling system might fail, as it cannot do anything else apart from wait for timeouts. This can be avoided by specifying shorter timeouts for the calls.

These concepts have been around much longer than the concept of microservices. The book Release It3 describes, in detail, these sorts of challenges and approaches for solving them. When these approaches are implemented, microservice-based systems can tolerate the failure of entire microservices and therefore become more robust than a deployment monolith.

3. Michael T. Nygard. 2007. Release It!: Design and Deploy Production-Ready Software. Raleigh, N.C.: Pragmatic Programmers.

When compared to deployment monoliths, microservices have the additional benefit that they distribute the system into multiple processes. These processes are better isolated from each other. A deployment monolith only starts one process, and therefore a memory leak or a piece of functionality using up a lot of computing resources can make the whole system fail. Often, these sorts of errors are simple programming mistakes or slips. The distribution into microservices prevents such situations, as only a single microservice would be failing in such a scenario.

Free Technology Choice

Microservices offer technological freedom. Since microservices only communicate via the network, they can be implemented in any language and platform as long as communication with other microservices is possible. This free technology choice can be used to test out new technologies without running big risks. As a test, one can use the new technology in a single microservice. If the technology does not perform according to expectations, only this one microservice has to be rewritten. In addition, problems arising from the failure will be limited.

The free technology choice means that developers really can use new technologies in production. This can have positive effects on both motivation and recruitment because developers typically enjoy using new technologies.

This choice also enables the most appropriate technology to be used for each problem. A different programming language or a certain framework can be used to implement specific parts of the system. It is even possible for an individual microservice to use a specific database or persistence technology, although in this situation, backup and disaster recovery mechanisms will need to be considered and implemented.

Free technology is an option—it does not have to be used. Technologies can also be imposed for all microservices in a project so that each microservice is bound to a specific technology stack. Compare this with a deployment monolith, which inherently narrows the choices developers have. For example, in Java applications, only one version of each library can be used. This means that not only the libraries used but even the versions used have to be set in a deployment monolith. Microservices do not impose such technical limitations.

Independence

Decisions regarding technology and putting new versions into production only concern individual microservices. This makes microservices very independent of each other, but there has to be some common technical basis. The installation of micro-services should be automated, there should be a Continuous Delivery pipeline for each microservices, and microservices should adhere to the monitoring specifications. However, within these parameters microservices can implement a practically unlimited choice of technical approaches. Due to the greater technological freedom, less coordination between microservices is necessary.

4.2 Organizational Benefits

Microservices are an architectural approach, and you could be forgiven for thinking that they only benefit software development and structure. However, due to Conway’s Law (see section 3.2), architecture also affects team communication, and thus the organization.

Microservices can achieve a high level of technical independence, as the last section (4.1) discussed. When a team within an organization is in full charge of a microservice, the team can make full use of this technical independence. However, the team also has the full responsibility if a microservice malfunctions or fails in production.

So, microservices support team independence. The technical basis enables teams to work on the different microservices with little coordination. This provides the foundation for the independent work of the teams.

In other projects, technology or architecture have to be decided centrally, since the individual teams and modules are bound to these decisions due to technical restrictions. It might just be impossible to use two different libraries or even two different versions of one library within one deployment monolith. Therefore, central coordination is mandatory. For microservices, the situation is different, and this makes self-organization possible. However, a global coordination might still be sensible so that, for example, a company is able to perform an update including all components because of a security problem with a library.

Teams have more responsibilities: they decide the architecture of their microservices. They cannot hand over this responsibility to a central function. This means they also have to take responsibility for the consequences, since they are responsible for the microservice.

This approach represents a significant change to traditional forms of organization where the central architecture group enforces the technology stack to be used by everybody. In this type of organization, the individual teams are not responsible for decisions or nonfunctional requirements like availability, performance, or scalability. In a classical architecture, the nonfunctional properties can only be handled centrally, since they can only be guaranteed by the common foundations of the entire system. When microservices do not force a common foundation anymore, these decisions can be distributed to the teams, enabling greater self-reliance and independence.

Smaller Projects

Microservices enable large projects to be divided into a number of smaller projects. As the individual microservices are largely independent of each other, the need for central coordination is reduced. This reduces the need for a large, centralized project management function with its associated communication overhead. When microservices enable the division of a large organization into several smaller ones, the need for communication reduces. This makes it possible for teams to focus more of their efforts on the implementation of requirements.

Large projects fail more frequently than smaller projects, so it is better when a large project can be divided into multiple smaller projects. The smaller scope of the individual projects enables more precise estimations. Better estimations improve planning and decrease risk. Even if the estimation is wrong, the impact is lower. Added to the greater flexibility that microservices offer, this can speed up and facilitate the process of decision making, particularly because the associated risk is so much lower.

4.3 Benefits from a Business Perspective

The previously discussed organizational benefits also lead to business advantages; the projects are less risky, and coordination between teams needs to be less intense so the teams can work more efficiently.

Parallel Work on Stories

The distribution into microservices enables work on different stories to occur in parallel (see Figure 4.3). Each team works on a story that only affects their own micro-service. Consequently, the teams can work independently, and the system as a whole can be simultaneously expanded in different places. This eventually scales the agile process. However, scaling does not take place at the level of the development processes, but is facilitated by the architecture and the independence of the teams. Changes and deployments of individual microservices are possible without complex coordination. Therefore, teams can work independently. When a team is slower or encounters obstacles, this does not negatively influence the other teams. Therefore, the risk associated with the project is further reduced.

Image

Figure 4.3 Example of Legacy Integration

An unambiguous domain-based design and the assignment of one developer team per microservice can scale the development or project organization with the number of teams.

It is possible that certain changes will impact several microservices and therefore several teams. For example, only certain customers are allowed to order certain types of product—for instance, because of age restrictions. In case of the architecture depicted in Figure 4.3, changes to all microservices would be necessary to implement this feature. The Customer microservice would have to store the data about whether a customer is of legal age. Product search should hide or label the products prohibited for underage customers. Finally, the order process has to prevent the ordering of prohibited products by underage customers. These changes have to be coordinated. Coordination is especially important when one microservice calls another. In that situation, the microservice being called has to be changed first so that the caller can use the new features.

This problem can certainly be solved, although one could argue that the outlined architecture is not optimal. If the architecture is geared to the business processes, the changes could be limited to just the order process. Eventually, only the ordering is to be prohibited, not searching. The information about whether a certain client is allowed to order or not should also be within the responsibility of the order process. Which architecture, and consequently which team distribution, is the right one depends on the requirements, microservices, and teams in question.

If the architecture has been selected appropriately, microservices can support agility well. This is certainly a good reason, from a business perspective, to use a microservice-based architecture.

4.4 Conclusion

In summary, microservices lead to the following technical benefits (section 4.1):

Strong modularization ensures that dependencies between microservices cannot easily creep in.

• Microservices can be easily replaced.

• The strong modularization and the replaceability of microservices leads to a sustained speed of development: the architecture remains stable, and micro-services that cannot be maintained any longer can be replaced. Thus, the quality of the system remains high in the long run, so that the system stays maintainable.

Legacy systems can be supplemented with microservices without the need to carry around all the ballast that has accumulated in the legacy system. Therefore, microservices are good to use when dealing with legacy systems.

• Since microservices are small deployment units, a continuous delivery pipeline is much easier to set up.

• Microservices can be scaled independently.

• If microservices are implemented in line with established approaches, the system will end up more robust.

• Each microservice can be implemented in a different programming language and with a different technology.

• Therefore, microservices are largely independent of each other on a technical level.

The technical independence affects the organization (section 4.2) in that the teams can work independently and on their own authority. There is less need for central coordination. This means that large projects can be replaced by a collection of small projects, which positively affects both risk and coordination.

From a business perspective, just the effects on risk are already positive (section 4.3). However, it is even more attractive that the microservice-based architecture enables the scaling of agile processes without requiring an excessive amount of coordination and communication.

Essential Points

• There are a number of technical benefits that range from scalability and robustness to sustainable development.

• Technical independence results in benefits at an organizational level. Teams become independent.

• The technical and organizational benefits result in benefits at the business level: lower risk and faster implementation of more features.


Try and Experiment

Look at a project you know:

• Why are microservices useful in this scenario? Evaluate each benefit by assigning points (1 = no real benefit; 10 = significant benefit). The possible benefits are listed in the conclusion of this chapter.

• What would the project look like with or without the use of microservices?

• Develop a discussion of the benefits of microservices from the perspective of an architect, a developer, a project leader, and the customer for the project. The technical benefits will be more of interest to the developers and architects, while the organizational and business benefits matter more for project leaders and customers. Which benefits do you emphasize most for the different groups?

• Visualize the current domain design in your project or product.

Which teams are responsible for which parts of the project? Where do you see overlap?

How should teams be allocated to product features and services to ensure that they can operate largely independently?


..................Content has been hidden....................

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