Chapter 11. Microservices

It seems like no book on programming these days is complete without at least some mention of microservices. For fear that this book could be singled out for ridicule as a non-conformant publication, a chapter has been included on microservices.

Microservices are billed as the solution to the problems of monolithic applications. Likely every application you've dealt with has been a monolith: that is, the application has a single logical executable and is perhaps split into layers such as a user interface, a service or application layer, and a data store. In many applications these layers might be a web page, a server side application, and a database. Monoliths have their issues as I'm sure you've encountered.

Maintaining a monolithic application quickly becomes an exercise in limiting the impact of change. Frequently in such applications a change to one, seemingly isolated, corner of the application has an unintended effect on some other part of the application. Although there are many patterns and approaches to describe well isolated components, these often fall by the wayside inside a monolith. Often we take shortcuts which may save time now but will return to make our lives terrible down the road.

Monolithic applications are also difficult to scale. Because we tend to have only three layers, we are limited to scaling each one of those layers. We can add more application servers if the middle tier is becoming slow or more web servers if the web tier is laggy. If the database is slow then we can increase the power of the database server. These scaling approaches are very large operations. If the only part of the application which is slow is signing up new users, then we really have no way to simply scale that one component. This means that components which are not frequently used (one might call these cold or cool components) must be able to scale as the whole application scales. This sort of scaling doesn't come for free.

Consider that scaling from a single web server to multiple web servers introduces the problem of sharing sessions between many web servers. If we were, instead, to divide our application into a number of services, of which each acts as the canonical source of truth for a piece of data, then we could scale these sections independently. A service for logging users in, another service for saving and retrieving their preferences, yet another for sending out reminder e-mails about abandoned shopping carts, each one responsible for its own functions and own data. Each service stands alone as a separate application and may run on a separate machine. In effect we have taken our monolithic application and sharded it into many applications. Not only does each service have an isolated function but it also has its own datastore and could be implemented using its own technology. The difference between a monolith and microservices can be seen here:

Microservices

Applications are written more by composing services than by writing singular monolithic applications. The UI of an application can even be created by asking a number of services to provide visual components to be slotted into a composite UI by some form of composing service.

Node.js' lightweight approach to building applications with just the required components makes it an ideal platform to build lightweight microservices. Many microservice deployments make heavy use of HTTP to communicate between services while others rely more heavily on messaging systems such as RabbitMQ or ZeroMQ. These two communication methods may be mixed in deployments. One might split the technology used along the lines of using HTTP against services which are query-only, and messaging against services which perform some action. This is because messaging is more reliable (depending on your messaging system and configuration) than sending HTTP requests.

While it may seem that we've introduced a great deal of complexity into the system it is a complexity that is easier to manage with modern tooling. Very good tooling exists for managing distributed log files and for monitoring the performance of applications for performance issues. Isolating and running many applications with virtualization is more approachable than ever with containerization technologies.

Microservices may not be the solution to all our maintenance and scalability issues but they are certainly an approach that is viable for consideration. In this chapter we'll explore some of the patterns that may assist in using microservices:

  • Façade
  • Aggregate services
  • Pipeline
  • Message upgrader
  • Service selector
  • Failure patterns

Because microservices are a relatively new development, there are likely to be many more patterns which emerge as more and more applications are created with the microservice approach. There is some similarity between the Microservices approach and Service Oriented Architecture (SOA). This means that there are likely some patterns from the SOA world which will be applicable in the microservices world.

Façade

If you feel that you recognize the name of this pattern, then you're correct. We discussed this pattern way back in Chapter 4, Structural Patterns. In that application of the pattern we created a class which could direct the actions of a number of other classes providing a simpler API. Our example was that of an admiral who directed a fleet of ships. In the microservices world we can simply replace the concept of classes with that of services. After all, the functionality of a service is not that different from a microservice – they both perform a single action.

We might make use of a façade to coordinate the use of a number of other services. This pattern is a base pattern for many of the other patterns listed in this chapter. Coordinating services can be difficult, but by putting them behind a façade we can make the entire application much simpler. Let us consider a service which sends e-mails. Sending e-mails is quite a complex process which may involve a number of other services: a username to e-mail address translator, an anti-malware scanner, a spam checker, a formatter to message the e-mail body for various e-mail clients, and so forth.

Most clients who want to send e-mail don't want to concern themselves with all of these other services so a façade e-mail-sending service can be put in place which holds the responsibility of coordinating other services. The coordination pattern can be seen here:

Façade
..................Content has been hidden....................

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