Key takeaways
|
Enterprises today contain a mix of services, legacy applications, and data, which are topped by a range of consumer channels, including desktop, web and mobile applications. But too often, there is a disconnect due to the absence of a properly created and systematically governed integration layer, which is required to enable business functions via these consumer channels. The majority of enterprises are battling this challenge by implementing a service-oriented architecture (SOA) where application components provide loosely-coupled services to other components via a communication protocol over a network. Eventually, the intention is to embrace a microservice architecture (MSA) to be more agile and scalable. While not fully ready to adopt an MSA just yet, these organizations are architecting and implementing enterprise application and service platforms that will enable them to progressively move toward an MSA.
In fact, Gartner predicts that by 2017 over 20% of large organizations will deploy self-contained microservices to increase agility and scalability, and it's happening already. MSA is increasingly becoming an important way to deliver efficient functionality. It serves to untangle the complications that arise with the creation services; incorporation of legacy applications and databases; and development of web apps, mobile apps, or any consumer-based applications.
Today, enterprises are moving toward a clean SOA and embracing the concept of an MSA within a SOA. Possibly the biggest draws are the componentization and single function offered by these microservices that make it possible to deploy the component rapidly as well as scale it as needed. It isn't a novel concept though.
For instance, in 2011, a service platform in the healthcare space started a new strategy where whenever it wrote a new service, it would spin up a new application server to support the service deployment. So, it's a practice that came from the DevOps side that created an environment with less dependencies between services and ensured a minimum impact to the rest of the systems in the event of some sort of maintenance. As a result, the services were running over 80 servers. It was, in fact, very basic since there were no proper DevOps tools available as there are today; instead, they were using Shell scripts and Maven-type tools to build servers.
While microservices are important, it's just one aspect of the bigger picture. It's clear that an organization cannot leverage the full benefits of microservices on their own. The inclusion of MSA and incorporation of best practices when designing microservices is key to building an environment that fosters innovation and enables the rapid creation of business capabilities. That's the real value add.
Addressing Implementation Challenges
The generally accepted practice when building your MSA is to focus on how you would scope out a service that provides a single-function rather than the size. The inner architecture typically addresses the implementation of the microservices themselves. The outer architecture covers the platform capabilities that are required to ensure connectivity, flexibility and scalability when developing and deploying your microservices. To this end, enterprise middleware plays a key role when crafting both your inner and outer architectures of the MSA.
First, middleware technology should be DevOps-friendly, contain high-performance functionality, and support key service standards. Moreover, it must support a few design fundamentals, such as an iterative architecture, and be easily pluggable, which in turn will provide rapid application development with continuous release. On top of these, a comprehensive data analytics layer is critical for supporting a design for failure.
The biggest mistake enterprises often make when implementing an MSA is to completely throw away established SOA approaches and replace them with the theory behind microservices. This results in an incomplete architecture and introduces redundancies. The smarter approach is to consider an MSA as a layered system that includes an enterprise service bus (ESB) like functionality to handle all integration-related functions. This will also act as a mediation layer that enables changes to occur at this level, which can then be applied to all relevant microservices. In other words, an ESB or similar mediation engine enables a gradual move toward an MSA by providing the required connectivity to merge legacy data and services into microservices. This approach is also important for incorporating some fundamental rules by launching the microservice first and then exposing it via an API.
Scoping Out and Designing the 'Inner Architecture'
Significantly, the inner architecture needs to be simple, so it can be easily and independently deployable and independently disposable. Disposability is required in the event that the microservice fails or a better service emerges; in either case, there is a requirement for the respective microservice to be easily disposed. The microservice also needs to be well supported by the deployment architecture and the operational environment in which the microservice is built, deployed, and executed. Therefore, it needs to be simple enough to be independently deployable. An ideal example of this would be releasing a new version of the same service to introduce bug fixes, include new features or enhancements to existing features, and to remove deprecated services.
The key requirements of an MSA inner architecture are determined by the framework on which the MSA is built. Throughput, latency, and low resource usage (memory and CPU cycles) are among the key requirements that need to be taken into consideration. A good microservice framework typically will build on lightweight, fast runtime, and modern programming models, such as an annotated meta-configuration that's independent from the core business logic. Additionally, it should offer the ability to secure microservices using desired industry leading security standards, as well as some metrics to monitor the behavior of microservices.
With the inner architecture, the implementation of each microservice is relatively simple compared to the outer architecture. A good service design will ensure that six factors have been considered when scoping out and designing the inner architecture:
First, the microservice should have a single purpose and single responsibility, and the service itself should be delivered as a self-contained unit of deployment that can create multiple instances at the runtime for scale.
Second, the microservice should have the ability to adopt an architecture that's best suited for the capabilities it delivers and one that uses the appropriate technology.
Third, once the monolithic services are broken down into microservices, each microservice or set of microservices should have the ability to be exposed as APIs. However, within the internal implementation, the service could adopt any suitable technology to deliver that respective business capability by implementing the business requirement. To do this, the enterprise may want to consider something like Swagger to define the API specification or API definition of a particular microservice, and the microservice can use this as the point of interaction. This is referred to as an API-first approach in microservice development.
Fourth, with units of deployment, there may be options, such as self-contained deployable artifacts bundled in hypervisor-based images, or container images, which are generally the more popular option.
Fifth, the enterprise needs to leverage analytics to refine the microservice, as well as to provision for recovery in the event the service fails. To this end, the enterprise can incorporate the use of metrics and monitoring to support this evolutionary aspect of the microservice.
Sixth, even though the microservice paradigm itself enables the enterprise to have multiple or polyglot implementations for its microservices, the use of best practices and standards is essential for maintaining consistency and ensuring that the solution follows common enterprise architecture principles. This is not to say that polyglot opportunities should not be completely vetoed; rather they need to be governed when used.
Addressing Platform Capabilities with the 'Outer Architecture'
Once the inner architecture has been set up, architects need to focus on the functionality that makes up the outer architecture of their MSA. A key component of the outer architecture is the introduction of an enterprise service bus (ESB) or similar mediation engine that will aide with the connecting legacy data and services into MSA. A mediation layer will also enable the enterprise to maintain its own standards while others in the ecosystem manage theirs.
The use of a service registry will support dependency management, impact analysis, and discovery of the microservices and APIs. It also will enable streamlining of service/API composition and wire microservices into a service broker or hub. Any MSA should also support the creation of RESTful APIs that will help the enterprise to customize resource models and application logic when developing apps.
By sticking to the basics of designing the API first, implementing the microservice, and then exposing it via the API, the API rather than the microservice becomes consumable. Another common requirement enterprises need to address is securing microservices. In a typical monolithic application, an enterprise would use an underlying repository or user store to populate the required information from the security layer of the old architecture. In an MSA, an enterprise can leverage widely-adopted API security standards, such as OAuth2 and OpenID Connect, to implement a security layer for edge components, including APIs within the MSA.
On top of all these capabilities, what really helps to untangle MSA complexities is the use of an underlying enterprise-class platform that provides rich functionality while managing scalability, availability, and performance. That is because the breaking down of a monolithic application into microservices doesn't necessarily amount to a simplified environment or service. To be sure, at the application level, an enterprise essentially is dealing with several microservices that are far more simple than a single monolithic, complicated application. Yet, the architecture as a whole may not necessarily be less arduous.
In fact, the complexity of an MSA can be even greater given the need to consider the other aspects that come into play when microservices need to talk to each other versus simply making a direct call within a single process. What this essentially means is that the complexity of the system moves to what is referred to as the "outer architecture", which typically consists of an API gateway, service routing, discovery, message channel, and dependency management.
With the inner architecture now extremely simplified--containing only the foundation and execution runtime that would be used to build a microservice--architects will find that the MSA now has a clean services layer. More focus then needs to be directed toward the outer architecture to address the prevailing complexities that have arisen. There are some common pragmatic scenarios that need to be addressed as explained in the diagram below.
The outer architecture will require an API gateway to help it expose business APIs internally and externally. Typically, an API management platform will be used for this aspect of the outer architecture. This is essential for exposing MSA-based services to consumers who are building end-user applications, such as web apps, mobile apps, and IoT solutions.
Once the microservices are in place, there will be some sort of service routing that takes place in which the request that comes via APIs will be routed to the relevant service cluster or service pod. Within microservices themselves, there will be multiple instances to scale based on the load. Therefore, there's a requirement to carry out some form of load balancing as well.
Additionally, there will be dependencies between microservices--for instance, if microservice A has a dependency on microservice B, it will need to invoke microservice B at runtime. A service registry addresses this need by enabling services to discover the endpoints. The service registry will also manage the API and service dependencies as well as other assets, including policies.
Next, the MSA outer architecture needs some messaging channels, which essentially form the layer that enables interactions within services and links the MSA to the legacy world. In addition, this layer helps to build a communication (micro-integration) channel between microservices, and these channels should be lightweight protocols, such as HTTP, MQTT, among others.
When microservices talk to each other, there needs to be some form of authentication and authorization. With monolithic apps, this wasn't necessary because there was a direct in-process call. By contrast, with microservices, these translate to network calls. Finally, diagnostics and monitoring are key aspects that need to be considered to figure out the load type handled by each microservice. This will help the enterprise to scale up microservices separately.
Reviewing MSA Scenarios
To put things into perspective, let's analyze some actual scenarios that demonstrate how the inner and outer architecture of an MSA work together. We'll assume an organization has implemented its services using Microsoft Windows Communication Foundation or the Java JEE/J2EE service framework, and developers there are writing new services using a new microservices framework by applying the fundamentals of MSA.
In such a case, the existing services that expose the data and business functionality cannot be ignored. As a result, new microservices will need to communicate with the existing service platforms. In most cases, these existing services will use the standards adhered to by the framework. For instance, old services might use service bindings, such as SOAP over HTTP, Java Message Service (JMS) or IBM MQ, and secured using Kerberos or WS-Security. In this example, messaging channels too will play a big role in protocol conversions, message mediation, and security bridging from the old world to the new MSA.
Another aspect the organization would need to consider is any impact to its scalability efforts in terms of business growth given the prevalent limitations posed by a monolithic application, whereas an MSA is horizontally scalable. Among some obvious limitations are possible errors as it's cumbersome to test new features in a monolithic environment and delays to implement these changes, hampering the need to meet immediate requirements. Another challenge would be supporting this monolithic code base given the absence of a clear owner; in the case of microservices, individual or single functions can be managed on their own and each of these can be expanded as required quickly without impacting other functions.
In conclusion, while microservices offer significant benefits to an organization, adopting an MSA in a phased out or iterative manner may be the best way to move forward to ensure a smooth transition. Key aspects that make MSA the preferred service-oriented approach is clear ownership and the fact that it fosters failure isolation, thereby enabling these owners to make services within their domains more stable and efficient.
About the Author
Asanka Abeysinghe is vice president of solutions architecture at WSO2. He has over 15 years of industry experience, which include implementing projects ranging from desktop and web applications through to highly scalable distributed systems and SOAs in the financial domain, mobile platforms, and business integration solutions. His areas of specialization include application architecture and development using Java technologies, C/C++ on Linux and Windows platforms. He is also a committer of the Apache Software Foundation.