27/04/2015

The Microservices Revolution

The latest buzz in enterprise application development surrounds the emergence of microservices. Although this term continues to grow in popularity
, there is still more to be learned about how these tiny powerhouses work and how they are changing the API environment.
To understand microservices, simply look to the name: micro-services. It is a new way of app building that breaks up application services into smaller, independent parts and functions.
With roots in SOA, DevOps and containers, microservices are seemingly part of architecture components we already know, but are unique in their flexible nature. Unlike traditional enterprise apps that are built as a monolithic piece of software, a microservices architectural style is an approach to developing applications as a suite of small services, running in its own process and communicating with lightweight protocols. The independent services, called microservices, are themselves not married to a specific language or platform. They can be easily and quickly adapted or altered to fit evolving application needs and functionality.
But what else is there to know about microservices? How should they be deployed and where do they fit best? As microservices continue to lead an enterprise app revolution, here are five things you need to know, presented by Akana, a leader in API management.

Pattern: Microservices Architecture

Context

You are developing a server-side enterprise application. It must support a variety of different clients including desktop browsers, mobile browsers and native mobile applications. The application might also expose an API for 3rd parties to consume. It might also integrate with other applications via either web services or a message broker. The application handles requests (HTTP requests and messages) by executing business logic; accessing a database; exchanging messages with other systems; and returning a HTML/JSON/XML response.
The application has either a layered or hexagonal architecture and consists of different types of components:
  • Presentation components - responsible for handling HTTP requests and responding with either HTML or JSON/XML (for web services APIS)
  • Business logic - the application’s business logic
  • Database access logic - data access objects responsible for access the database
  • Application integration logic - messaging layer, e.g. based on Spring integration.
There are logical components corresponding to different functional areas of the application.

Problem

What's the application's deployment architecture?

Forces

  • There is a team of developers working on the application
  • New team members must quickly become productive
  • The application must be easy to understand and modify
  • You want to practise continuous deployment of the application
  • You must run multiple copies of the application on multiple machines in order to satisfy scalability and availability requirements
  • You want to take advantage of emerging technologies (frameworks, programming languages, etc)

Solution

Architect the application by applying the Scale Cube (specifically y-axis scaling) and functionally decompose the application into a set of collaborating services. Each service implements a set of narrowly, related functions. For example, an application might consist of services such as the order management service, the customer management service etc.
Service communicate using either synchronous protocols such as HTTP/REST or asynchronous protocols such as AMQP.
Services are developed and deployed independently of one another.
Each service has its own database in order to be decoupled from other services. When necessary, consistency is between databases is maintained using either database replication mechanisms or application-level events.

Example

Let’s imagine that you are building an e-commerce application that takes orders from customers, verifies inventory and available credit, and ships them. The application consists of several components including the StoreFrontUI, which implements the user interface, along with some back end services for checking credit, maintaining inventory and shipping orders.
The application is deployed as a set of services.
Resulting context
This solution has a number of benefits:
  • Each microservice is relatively small
    • Easier for a developer to understand
    • The IDE is faster making developers more productive
    • The web container starts faster, which makes developers more productive, and speeds up deployments
  • Each service can be deployed independently of other services - easier to deploy new versions of services frequently
  • Easier to scale development. It enables you to organise the development effort around multiple teams. Each (two pizza) team is responsible a single service. Each team can develop, deploy and scale their service independently of all of the other teams.
  • Improved fault isolation. For example, if there is a memory leak in one service then only that service will be affected. The other services will continue to handle requests. In comparison, one misbehaving component of a monolithic architecture can bring down the entire system.
  • Each service can be developed and deployed independently
  • Eliminates any long-term commitment to a technology stack
This solution has a number of drawbacks:
  • Developers must deal with the additional complexity of creating a distributed system.
    • Developer tools/IDEs are oriented on building monolithic applications and don't provide explicit support for developing distributed applications.
    • Testing is more difficult
    • Developers must implement the inter-service communication mechanism.
    • Implementing use cases that span multiple services without using distributed transactions is difficult
    • Implementing use cases that span multiple services requires careful coordination between the teams
  • Deployment complexity In production, there is also the operational complexity of deploying and managing a system comprised of many different service types.
  • Increased memory consumption The microservices architecture replaces N monolithic application instances with NxM services instances. If each service runs in its own JVM (or equivalent), which is usually necessary to isolate the instances, then there is the overhead of M times as many JVM runtimes. Moreover, if each service runs on its own VM (e.g. EC2 instance), as is the case at Netflix, the overhead is even higher.
One challenge with using this approach is deciding when it makes sense to use it. When developing the first version of an application, you often do not have the problems that this approach solves. Moreover, using an elaborate, distributed architecture will slow down development. This can be a major problem for startups whose biggest challenge is often how to rapidly evolve the business model and accompanying application. Using Y-axis is splits might make it much more difficult to iterate rapidly. Later on, however, when the challenge is how to scale and you need to use functional decomposition then tangled dependencies might make it difficult to decompose your monolithic application into a set of services.
Another challenge is deciding how to partition the system into microservices. This is very much an art but there are number of strategies that can help. One approach is to partition services by verb or use case. For example, later on you will see that the partitioned e-commerce application has a Shipping service that’s responsible for shipping complete orders. Another common example of partitioning by verb is a login service that implements the login use case.
Another partitioning approach is to partition the system by nouns or resources. This kind of service is responsible for all operations that operate on entities/resources of a given type. For example, later on you will see how it makes sense for the e-commerce system to have an Inventory service that keeps tracks whether products are in stock.
Ideally, each service should have only a small set of responsibilities. (Uncle) Bob Martin talks about designing classes using the Single Responsible Principle (SRP). The SRP defines a responsibility of class as a reason to change, and that a class should only have one reason to change. It make sense to apply the SRP to service design as well.
Another analogy that helps with service design is the design of Unix utilities. Unix provides a large number of utilities such as grep, cat and find. Each utility does exactly one thing, often exceptionally well, and can be combined with other utilities using a shell script to perform complex tasks.

No comments:

Post a Comment