Takeaways from microservice antipatterns:
- Overzealous Services – don’t go straight into microservices, (following the hype perhaps?) rather than starting with the simplest thing possible. Instead, you should start by doing the simplest thing possible, identify the hotspots as they become apparent and then extract them into microservices. Start with monolith.
- Schemas Everywhere – avoid having a shared database between different services. This creates tight coupling between the services and means you can’t deploy the microservices independently if it breaks the shared schema. Any schema updates will force you to update other microservices too. Instead, every service should have its own database, and when you want data from another service you go through its API rather than reaching into its database and help yourself. Use semantic versioning.
- Spiky Load between Services – You often get spiky traffic between services, and a common solution is to amortise the load by using queues between the services. Use rabbitmq.com, redis, etc.
- Hardcoded IPs and Ports – One solution would be to use a discovery service such as consul or etcd, and there’s also Netflix’s eureka. Another solution is to use a centralised router. Both solutions require registration and deregistration, and both require high availability and scalability.
- Dogpiles – If one of your services is under load or malfunctioning, and all your other services keep retrying their failed calls, then the problem would be compounded and magnified by the additional load from these retries. The solution here is to have exponential backoff and implement the circuit breaker pattern. Many libraries such as Netflix’s Hystrix and Polly for .Net are available. You can even use the service discovery layer to help propagate the message to all your services that a circuit has been tripped (i.e. a service is struggling).
- Debugging Hell – Debugging is always a huge issue in micro-service architectures. E.g., a nested service call fails and you can’t correlate it back to a request coming from the user. One solution is to use correlation IDs. When a request comes in, you assign the request with a correlation ID and pass it on to other services in the HTTP request header. Every service would do the same and pass the correlation ID it receives in the incoming HTTP header in any out-going requests. Whenever you log a message, be sure to include this correlation ID in the log line.
- Missing Mock Servers – When you have a service that other teams depend on, each of these teams would have to mock and stub your service in order to test their own services. A good step in the right direction is for you to own a mock service and provide it to consumers. You can take it a step further, by building the mock service into the client so you don’t even have to maintain a mock service anymore. Use Anypoint Platform or Swagger.
- Flying Blind – There are more than a handful of tools available in this space. There are commercial tools (some with free tiers) such as NewRelic and StackDriver (now integrated into Google AppEngin), AWS also offers CloudWatch as part of its ecosystem. In the open source space, Netflix has been leading the way with Hystrix and something even more exciting.
- Richard Rodger – Measuring Micro-services – Codemotion Rome 2015