Are Microservices Good?
The term Microservice has come to mean many different things. One definition is that a Microservice should be no more than 100 lines of code. Another claims that it’s not 100 lines, but 400. Yet another asserts that it’s 1,000 lines. There are at least a few problems with all of these attempted definitions, which probably reflect more on the name itself. The term “micro” is often seen to imply size—but what does “micro” mean?
When using “micro” to describe computer CPUs, the full term is microprocessors. The basic idea behind a microprocessor is that it packs all the functionality of a CPU onto one or a few integrated circuits. Before the design and availability of microprocessors, computers typically relied on a number of circuit boards with many integrated circuits.
Note, however, that the term microprocessor doesn’t carry the idea of size, as if some arbitrary specific number of integrated circuits or transistors is either appropriate or not. Figure 1.9 shows a case in point—that one of the most powerful CPUs available is still a microprocessor. For example, the 28-core Xeon Platinum 8180 sports 8 billion transistors. The Intel 4004 had 2,250 transistors (year 1971). Both are microprocessors.
Figure 1.9 The Intel Xeon is one of the most powerful modern microprocessors. No one has said it is not a microprocessor because it has “too many circuits and transistors.”
Microprocessor limits are generally set based on purpose; that is, some microprocessor types simply don’t need to provide the power of others. They can be used for small devices that have limited power resources, and thus should require less draws on power. Also, when the power of a single microprocessor—even one of outstanding proportions—is not enough for the computing circumstances, computers are supplied with multiple microprocessors.
Another problem with putting some arbitrary limit on the number of lines of code in a Microservice is the fact that a programming language has a lot to do with the number of lines of code required to support some specific system functionality. Saying that this limit is 100 lines of code for Java is different than saying it is 100 lines of code for Ruby, because Java tends to require 33% more code than Ruby. In a matchup of Java versus Clojure, Java requires around 360% more lines of code.
Furthermore, and even more germane to the point, creating tiny-tiny Microservices has been shown to result in a number of disadvantages:
The sheer number of Microservices can grow beyond hundreds, to thousands, and even tens of thousands.
Lack of dependency comprehension leads to unpredictability of changes.
Unpredictability of change results in no changes or decommissioning.
More Microservices are created with similar (copy-paste) functionality.
The expense of ever-growing yet often obsolete Microservices increases.
These major disadvantages suggest that the result is unlikely to be the hoped-for cleaner distributed system solution and autonomy. With the background given in this chapter, the problem should be apparent. In essence, the many tiny-tiny Micro-services have created the same situation as the Monolithic Big Ball of Mud, as seen in Figure 1.10. No one understands the system, which falls prey to the same issues that are experienced with a Monolithic Big Ball of Mud: haphazard structure; unregulated growth; repeated, expedient repair; information shared promiscuously; all important information global or duplicated.
Figure 1.10 Many tiny-tiny Microservices result in a distributed Big Ball of Mud.
Some solutions and additional efforts may be made to move beyond these outcomes, but they generally do not use a completely separate container deployment per Microservice.
The best way to think about a Microservice is not by defining the size, but rather by determining the purpose. A Microservice is smallish in comparison to a Monolith, but the guidance we provide is to avoid implementing tiny-tiny Microservices. These points are discussed in detail later, in Part II of this book.