Microservices architecture, though it sounds interesting and proving to be hugely popular, comes with its own set of challenges. We will look at a few challenges posed by this architecture.
A typical Microservices based application deployed in the Cloud could have a large number of services and each service in turn can have a large number of instances (scaled horizontally). This setup can pose varying challenges as detailed out below:
1. Service Discovery
With a large number of services/instances, it becomes important to identify and locate each service/instance. Similarly, as we add/remove new services/instances, other services need to know about this.
Use a service registry which maintains a registry of services, their end points and their instances. Some load balancers also maintain service registry. We can use client side/server side load balancers which also maintain service registry. E.g., we can use Load balancers like Eureka, Consul.
With a large number of services/instances, it becomes important to collect the logs at a centralized location. If the logs are not centralized then, we would have to go into different servers to check the logs for troubleshooting and this process is very cumbersome and painful. If a request spans across a number of services, it is also important to trace the request across all services.
- Centralized Logging solutions like Splunk or Elastic Search, Logstash, Kibana (Known as ELK Stack), or cloud based log aggregators like Papertrail could be used to collect the logs at a centralized location.
- Logs could be enhanced by adding suitable header info (meta data info) which identifies a request and ties the log message to a request.
With a large number of services/instances, it becomes very crucial to monitor the service instances, monitor their performance, health, memory status etc.
Monitoring tools like New relic, Sensu could be used to monitor the services, gather performance metrics and configure alerts.
Because of the distributed nature of the application, securing every end point/services takes high priority. Also, a single insecure end point can prove to be a weak link in the chain and lead to catastrophes.
The end points could be secured using security protocols like OAUTH.
Since a single cohesive monolithic application is now decomposed into numerous independently deployable microservices, it might cause a dip in performance and will need sufficient performance monitoring and tuning as needed.
6. Deployment challenges
With a large number of services/instances, deploying each service can become challenging. This might become complicated if different services are built using different programming languages and require different run time environments. Also, deploying to a huge number of servers could pose challenges with rollback if something goes wrong.
- Use automated deployment processes
- Use Platform as a Service
- Use Containers for deployment
- Use Blue Green or Canary deployment techniques
7. Database challenges
Use of polyglot persistence might require diverse database skills (SQL/NOSQL), while administering the application. Microservices generally use one database per service and the database changes and application deployments need to be synchronized.
8. API Management
With microservices architecture, generally API driven development is followed and it becomes important to properly manage the APIs. The management of APIs would include the following aspects:
- Versioning of APIs
- Maintaining backward compatibility of APIs
- Documenting API interfaces
- Metering of APIs (If the APIs are exposed to third party vendors or to the public and if each invocation of the API is billed, then we would need to log and price each API invocation).
A lot of API management solutions like Apigee, WSO2, and Kong are available which could be used.
9. Integration Testing
With microservices architecture having large number of services, inter communication between services becomes inevitable. This brings in Integration testing challenges with each release.
Use Integration testing tools like Citrus or Pact.
10. Fault Handling
With microservices architecture having large number of services, a failure in one service could lead to a cascading failure in all dependent services and this could quickly gulp system resources. Obviously, robust fault handling is very crucial and needs to be designed and built into the system.
Use patterns like Circuit breaker which works like electric circuit breakers. If a service call fails, it will fall back to a Fail over implementation, until the service comes back to normalcy. Also the system should fail fast, so that the issues are quickly noticed and resolved.