Blogs

Getting Your Microservices Strategy right!

Rajesh Dangi / October 29th, 2019

Beyond the Cloud

Getting Your Microservices Strategy right!

In my article in 2015, we have touch based on the fundamentals of Micro-Services, the momentum has picked up and that warrants revisiting the approach and strategies of microservices that are transforming the landscape of the application architecture and consumption thereof redefining the design, development, data and delivery aspects even today at much more larger way. It is challenging the legacy approach of monolithic architecture by paving way for distributed, loosely coupled, inter-connected and highly scalable ecosystem of functionalities called as fine-grained services. The strategy is to move out capabilities vertically, decouple the core capability with its data and redirect all front-end applications to the new APIs, in this era of microservices…

What are Micro-services and how are they different from Containers?

Microservices, i.e. microservices architecture (MSA) is a resilient application architecture, a development / testing technique or style that structures an application as a collection of services that are isolated and loosely coupled with each other. Simply put, collection of processes, self-contained piece of business functionality with clear interfaces that are communicating over network as per the defined workflow and set goals and may contain everything from the operating system, platform, framework, runtime and dependencies, packaged together for execution.

Containers on the other hand, encapsulate discrete components of application logic, libraries, frameworks, etc provisioned only with the minimal resources needed to do their job and can run independently isolating applications from one another, without dependency on OS, platform and the underlying running infrastructure resources. Simply put, pack your code, discrete components of application logic and its dependencies into a container that can then run anywhere with the minimal resources needed to do the job.

A microservice may run in a container, but it could also run as a fully provisioned VM on cloud. Likewise, a container doesn’t have to be used for microservices, even though containers are a good way to develop and deploy them. The containerization of the applications ensures an easily distributed architecture and cloud-to-cloud portability. While running on cloud, enablement of the application to externalize APIs and microservices is the best path for applications to provide the best functionality on cloud platforms since they are autonomous and have independent ability to scale-out a specific microservice on-demand. Any e-commerce application can be broken down into microservices, key application modules such as log-in, transaction history, current inventory, viewing deals and combos or product catalog, recommendations, shopping carts, check out, payment gateways, payment receipt and finally tracking the shipments are all interconnected yet standout modules that can be developed, tested independent of each other and still respect the workflow and security of each user, product, transaction and payments.

Beyond the Cloud

Microservices can be implemented in different programming languages and might use different infrastructures whereas containers are independent of it. Microservices allow you to separate sensitive data and add more careful security to that data. Furthermore, by ensuring all traffic between microservices is secured, a microservices approach could make it harder to exploit a break-in.

Types of Microservices...

Largely, microservices are of two types, stateful and stateless.

The Stateful microservices save session information within the code and the runtime cache. When a stateful service terminates it has to save its state. Stateful microservices possess saved data in a database that they read from and write to directly. Note that well-behaved stateful microservices don’t tend to share the databases with other microservices because that makes it hard to maintain decoupling and well-defined interfaces. Typically, these stateful services offload persistence to host its running on thus in-adversely locks itself to the same host to re-launch the service and maintain the stickiness to session. Many use Technologies, such as PortWorx, Flocker and Docker volume plugins, address this problem by creating a separate persistence layer that’s not host-dependent.

Stateless microservices on the other hand do not retain the session state between requests. They do not link requests in the way that stateful microservices do. They handle requests and return responses. Everything they need to know is supplied on the request and once the request is complete, they forget it. Stateless microservices are often used for transactions that return specific results and run only as they are required to produce those results. Stateless services can also scale because any service instance can run a request and get the same result.

Key Advantages

  • Responsive – adopting a microservice architecture can continuously deliver capabilities according to the customer’s changing needs, helping businesses response quickly to the changing consumer / customer needs and market dynamics.
  • Continuous Delivery- Microservices built on the principles of Agile and DevOps ( Read, CI/CD) help the development teams run parallel projects while iterating quickly on discrete capabilities without impacting release cycles and overall system downtimes for upgrade.
  • Scalability and Reliability - A successful microservice architecture prevents against any system failure. Its repeatable automation, scaling application, and designing pattern features keep the system running and scaling up or down based on consumption.

The Layered Approach

Since microservices are components of a single application workflow of functionalities, ecosystem of microservices must be integrated and tightly coupled with each other. The layered approach of this integration between core services, composite services and edge services (Read, API services) must work in tandem and provide individual component scalability and still preserve granular capabilities thereof.

Beyond the Cloud

  • Core Services Layer – runs the business logic and are mostly independent of each other, many of these services interact with databases for updates and retrieval based on the application workflow but rarely interact with external systems or components. Changes in the business logic, additional feature sets etc are thus published in agile way without compromising the performance of functionality and provide significant value via isolation and ease of augmentation of such functionalities for test and development etc. once published the core services can be consumed by composite services via application workflow/ user interaction. Many of the core services are stateless and does not depend on the other core services for persistence. The persistence services must have a composite service component owner to prevail in case of failure of the one or more services, typically such services are data centric and work along with specific caching or persistence datastore.
  • Composite Services Layer – are the key workflow managers which connect edge to the core in one to many and contains business logic or routing, they decide which core services to call, how to do data type mapping, orchestrate dynamic workflows between edge and core components and might occasionally interact with external systems via API services to make sure network communication logic, inter-service communication through various protocols and resiliency of the wholesome service layer remains intact while being choreographed.
  • Edge Services Layer – are the perimeter layer of the microservices and focus on the API versioning, routing and session management as fundamental deliverable. A set of value-added metering, compositions, security measures are deployed at this layer to ensure such overheads are not burdening the composite or core services. Connections out to external services require special attention since they cross network boundaries. These services should be resilient to outages of remote components. Gateways contain logic to handle such error cases. The edge layer might get extended to multiple locations or clusters for a true resilient and distributed presence yet work cohesively with composite services wherever they are published for consumption.

Overall, Service boundaries are closely tied to business demands and hierarchy boundaries of the application workflow / logic and times span across entities and stakeholder components running across multiple systems and locations, yet respect service interactions, APIs and data structure protocols thereof. In principle every microservice architecture must strive to keep things as straightforward as possible to avoid tight coupling of the components. In some cases, you might be using an event-driven architecture with asynchronous message-based communications. But then ayou should look into basic message queue services like RabbitMQ and avoid adding complexity to the messages transmitted over the network and maintain consistency and integrity of data that serves multiple microservices.

Beyond the Cloud

In short, having a microservice architecture makes developing and maintaining each business capability easier. But things become more complicated when you look at all the services together and how they need to interact to complete actions. The modern microservices system is distributed with multiple points of failure and by principle of design, one need to cater for that and take in account not only issues where a service is not responding, but also be able to deal with slower network responses, latencies from external edge services, clean recovery from a failure can become tricky at times as you need to make sure that services that get back up and running do not get flooded by pending messages or stale requests etc.

Key Considerations…

Building microservices is a journey rather than the immediate goal, it is recommended to start small to understand the technical requirements of a distributed system, how to fail gracefully and even scale individual components at ease. Once this is mastered one can gradually increase the scope and complexities adding more and more services with expertise and experience.

  • Strong Module Boundaries: Microservices reinforce modular structure, which is particularly important for larger teams or large-scale applications. A microservice architecture is the natural consequence of applying the single responsibility principle at the architectural level. This results in a number of benefits over a traditional monolithic architecture such as independent deployability, language, platform and technology independence for different components, distinct axes of scalability and increased architectural flexibility.
  • Independent Deployment: Simple services are easier to deploy, and since they are autonomous, are less likely to cause system wide failures when they go wrong.
  • Technology Diversity: With microservices you can mix multiple languages, development frameworks and data-storage technologies leveraging available skills and gain advantage on time to market.
  • Distribution: Distributed systems are harder to program, since remote calls are slow and are always at risk of failure. It requires vision and evangelizations to ensure everyone works on small services but keeps in mind overall picture.
  • Eventual Consistency: Maintaining strong consistency is extremely difficult for a distributed system, which means everyone has to manage eventual consistency.
  • Operational Complexity: You need a mature operations team to manage lots of services, which are being redeployed regularly and yet don’t break often. You have to understand the baselines of the different microservices and be able to react not only when they go down, but also when they're behaving unexpectedly all by automating the monitoring and remediation as separate set of system hygiene services or watchdogs.
  • Service Mesh - Microservice-based applications are sometimes combined with a Service Mesh such as Istio or Linkerd to encapsulate the challenges that arise from having to establish, manage and secure service-to-service communication. A service mesh is a configurable, low‑latency infrastructure layer designed to handle a high volume of network‑based inter-process communication among application infrastructure services using application programming interfaces (APIs). A service mesh ensures that communication among containerized and often ephemeral application infrastructure services is fast, reliable, and secure. The mesh provides critical capabilities including service discovery, load balancing, encryption, observability, traceability, authentication and authorization, and support for the circuit breaker pattern.
  • Cyclic dependency - Dependency management across different services and their functionality is very important and cyclic dependencies can be a headache if not identified and resolved promptly.
  • Security of Application: The proliferation of services in the architecture creates more soft targets for hackers, crackers and criminals. With a variety of operating systems, frameworks and languages to keep track of, the security group will have their hands full making sure the system is not vulnerable and they have complete visibility and surveillance across such tools and techniques.
  • Caching: Caching helps reduce the number of requests service needs to make. Caching requests that involve a multitude of services can grow complicated quickly, necessitating communication from different services and their development teams.
  • Fault Tolerance: The watchword with microservices is “interdependence.” Services have to be able to withstand outright failures and inexplicable timeouts. Failures can multiply quickly, creating a cascading effect through some services, potentially spiking services needlessly. Fault tolerance in this environment is much more complicated than a monolithic system.

In Summary, Microservices is a strategy that is beneficial to both raw technical code development process, and overall business organization strategy. Microservices help organize development teams into units that focus on developing and owning specific business functions to maintain granular focus that improves the overall business communication and efficiency.

The key to digital transformation success is finding ways to access the mission-critical data stored on legacy systems and putting it to work. Microservices, with APIs, make complex development easier. Legacy Monolith application architecture and microservices architecture adoption is not a simple binary choice. Both have fuzzy definitions, different criteria and goals to achieve that tells us that many systems might still be on a boundary area and few might not even fit into either category. Most of us, including me, keep talking about microservices in contrast to monoliths because it makes sense to acknowledge that there are systems out there that don't fit comfortably into either category or might be in evolving stage to fit into one. Let’s think of monoliths and microservices as two regions in the space of architectures with interesting characteristics that are useful to discuss as viable options wrt to goals they are set forth to achieve but no sensible enough to treat them as a comprehensive partitioning of the architectural space. What Say?

***

Oct 2019. Compilation from various publicly available internet sources, authors views are personal.