Thursday 18 June 2015

Microservices



Recently, there has been a large push away from monolithic application in favor of small, composable, purpose-built micro-services. To me, micro-services are autonomous services that take full responsibility for one business capability. Full responsibility includes presentation, API, data storage and business logic.

Each micro-service is aligned with a specific business function, and only defines the operations necessary to that business function. This may sound exactly like service-oriented architecture (SOA), and indeed, micro-services architecture and SOA share some common characteristics. Both architectures organize code into services, and both define clear boundaries representing the points at which a service should be decoupled from another. However, SOA arose from the need to integrate monolithic applications that exposed an API (usually SOAP-based) with one another. In SOA, integration relies heavily on middle-ware, in particular enterprise service bus (ESB). Micro-services architecture may often make use of a message bus, but there is no logic in the messaging layer whatsoever—it is purely used as a transport for messages from one service to another. This differs dramatically from ESB, which contains substantial logic for message routing, schema validation, message translation, and business rules. As a result, micro-services architectures are substantially less cumbersome than traditional SOA, and don’t require the same level of governance and canonical data modeling to define the interface between services. With micro-services, development is rapid and services evolve alongside the needs of the business.
Moreover the focus of SOA is separation of concern at interface level where micro-services describe the entire deployment scenario.

Another key advantage of the micro-services architecture is that a service can be individually scaled based on its resource requirements. Rather than having to run large servers with lots of CPU and RAM, micro-services can be deployed on smaller hosts containing only those resources required by that service.

As micro-services architecture is a significant shift from monolithic approach it may require restructuring of several components of the architecture landscape. In this article we we discuss some of the more significant ones.

Authentication :

In traditional monolithic application a user would provide a username,password which would be verified and and a user session would be created. All messaging withing the application is usually in context of this user session. In micro-service architecture the entire flow cannot be encapsulated under an user session as it would make the whole application stateful. It needs to be split into external (the API gateway), and internal (between services) authentication. External authentication with user would be handled by an authentication micro-services which can verify a user and issue an authentication token. This token can be passed between micro services to establish authentication.

However this would mean multiple micro services relying on auth server in order to authorize resources. At some point it can run into performance issues due to too many round trips to authentication server. There may be also scalability issues for auth server as number of micro services increases. An alternate approach is to split micro-services into frontend and backend micro-services. Frontend micro-services can use authentication token mechanisms as discussed. Backend micro-services will use App-specific API tokens for each backend service . Every backend micro-service will have its own AppId which can be locally validated by other micro-services.

Service Lookup:

When building micro-services, you have to naturally distribute your application around a network. That means that your services need to be reconfigured with the location of the other services they need to connect to. This reconfiguration needs to be able to happen on the fly, so that when a new service instance is created, the rest of the network can automatically find it and start to communication with it. This process is called Service Discovery.

Apache ZooKeeper is one of tool that can be used for service discovery as it provides a distributed, eventually consistent hierarchical configuration store.

Deployment:

As number of micro-services grow it can be difficult to keep track of which hosts are running certain services. Also if services are implemented in different programming languages, this means the deployment of each service will require a completely different set of libraries and frameworks, making deployment to a server complex.A container technology like Docker provides an ideal solution for this scenario as it creates containers that comprise of just the application and its dependencies. It is this isolation between containers running on the same host that makes deploying micro-service code developed using different languages and frameworks very easy.

Persistence:
In micro-services like isolation of service it is also important to have isolation of data. To ensure loose coupling, each service has its own database (schema). Moreover, different services might use different types of database – a so-called polyglot persistence architecture. For example, a service that needs ACID transactions might use a relational database, whereas a service that is manipulating a social network might use a graph database.
If there is some data that is needed in more than 1 service, there will be one service that is the owner of the data and exposes it over an API.

Tracing & Auditing:
As there are different servers so just looking and finding problem in logs can become big pain.What we need to do is  tag each request and each event with a request-id. This id can be generated when the first request enters the system and can be used for every event and request that is triggered after that. That request-id can be used as a tag in the logs. Logstash with Kibana are open source tools that can be be utilized here.Logstash allow to aggregate logs into one location, and Kibana allow to search log files.So we can trace the entire flow in Kibana using the request-id tag.


Hopefully this high level overview is helpful when designing your own micro-service architectures
There are various strategies for incrementally evolving an existing monolithic application to a micro-service architecture. It also makes sense to iteratively identify components to extract from the monolith and turn into services. While the evolution is not easy, it’s better than trying to develop and maintain an unwieldy monolithic application.