Evolution of software architecture
Before we can understand the details behind microservices architecture, let’s take a brief look at how software architectures have evolved.
About a decade ago, the monolithic application was very popular, and consequently its N-tiered architecture backbone was a norm. This consisted of an application decomposed into several layers. These layers vary depending on the complexity of the application, but traditionally, there were three main components. See Figure 1-1.
FIGURE 1-1 The monolithic architecture model
Presentation layer The presentation layer traditionally represents the front-end. Some of the artifacts include view models, view pages, user interfaces, and other artifacts that are oriented toward front-end development.
Business layer The middle layer is a business layer that holds all the logical flows of the application. This includes most of what we consider as the back-end code necessary for the primary function of the overall application. This area is where languages such as .NET or even Java are used to build back-end services that contain business managers and business objects consisting of the application logic.
Data access layer Finally, the data access layer is responsible for all database operations. This consists of a database and interface to perform read/write operations on data collected and used within the application as part of its overall functionality.
This layered architecture provides a basic separation of concerns and decomposition of applications into functional components. However, this architecture results in tightly coupled services that result in many dependencies.
Thinking of some of the scenarios from earlier, we can see why tightly coupled services and dependencies cause problems. Dependencies present drawbacks where it is difficult to make any changes to the application easily. This includes complexity in the form of large migrations and refactoring projects where many teams are involved and many times agility is replaced with a potential for bureaucracy. This introduces longer timelines because simple quick deployments cannot be made and ultimately all these problems cascade into a single point where management is then required to make massive expenditures.
Service-oriented architecture (SOA)
The transition away from monolithic architecture was driven by these reasons. The heavyweight nature of this architecture was slowly decomposed and eventually led to the formation of a new architecture known as service-oriented architecture (SOA), which is illustrated in Figure 1-2.
FIGURE 1-2 SOA architecture
This model was geared toward decomposing an application into even more granular modules to account for the drawbacks in monolithic architectures. Essentially, SOA was a way to connect different monoliths across a consistent messaging channel. Thus, as you can see in Figure 1-2, with SOA, you can have a set of services that are serving various functions connect and communicate with each other over a service bus. This service bus essentially is the communication tool that assists with message routing, transformations, security improvement, logging, and much more.
Because the services are broken down by function, it is slightly easier to deploy changes that don’t affect the whole application. So, if you were building an application with a monolithic architecture, you could refactor it by using SOA architecture and addressing the litany of cascading problems we had with the monolithic architecture. Although SOA addresses some of these problems, we haven’t solved a primary pain point in either architecture model—assuaging application scalability concerns.
Application scalability is an important design consideration when thinking about the growth of the application over time. With a larger user base, you will likely have more complex requirements, and thus considerations must be in place for handling additional requests and traffic. The clunky nature of the monolithic architecture doesn’t address this and neither does SOA. Ultimately, with more scale, SOA breaks down internally because the single enterprise bus is overwhelmed, which slows (or throttles) during periods of increased requests and traffic.
That being said, the SOA concept ultimately introduced an important integration solution that helped applications talk to each other, and the additional consideration of scalability gave way to the expansion of the microservices architecture.