5 Best Practices for REST-Based Microservices
Your microservice architecture will be more developer-friendly and resilient if you follow these best practices when designing your architecture.
Join the DZone community and get the full member experience.
Join For FreeIn this tutorial, we will discuss five best practices with which you can make your microservice architecture developer-friendly so they can manage and track the error easily.
User-Agent: It is very important to provide a meaningful name in the request header, so if any problem like slowness, huge memory access, or a spike occurs, developers can understand from which microservice this request originated. It is a best practice to provide the logical name/{service id } in the User-Agent property in the Request header. Ex : User-Agent:EmployeeSearchService
API Version Control: In REST-based microservice architecture, one microservice accesses another microservice's resources via API. The API acts as a facade to other microservices. The utmost important part is to write the API in a judicious way so that the API is not changed frequently because other microservices consume it, so any changes in the API method signature break other codes. The irony is, change is inevitable as we don't know the future, so today's business strategy may become old in a few days, so the API must be revamped. As an architect, the main challenge is how to cope with these changes. The answer is maintaining the version. For major changes, you can update the API version and provide notice to your consumers that new version has arrived so they can migrate to the new version within a defined timeframe. In this timeframe, as an API provider, you have to maintain both versions and constantly send important notices to your consumer to migrate their codebase call to the new version, and after that period, you can decommission your old version.
Correlate ID: We know that a business functionality in a microservice architecture is distributed over multiple microservices, so one request from a client internally fans out to many separate requests and it is highly probable that one of the services is slow or down. But as a developer, we need to know how to track which service is slow in the microservice forest, so somehow we need to group the requests logically. It is always a good practice to generate a random UUID for a client request and pass that UUID to every internal request so in a log we can track by the UUID and find the call trace accordingly.
ELK Implementation: Microservices are meant for autoscaling, so in a complex business domain, it is very hard to manage log files for microservices. In a system, say there are 50 microservices involved and each has 10 instances; there will be 50*10=500 logs files generated. As a developer, it is not possible to log into each instance and collect logs to investigate an issue, so we need a centralized mechanism where all logs are dumped and we can do some intelligent searching over that log, like finding an error or a particular exception or search by the host, correlate ID, etc. ELK provides this functionality, where E stands for ElasticSearch, L is Logstash, and K is Kibana. ElasticSearch dumps the logs and provides a fuzzy search capability, Logstash is used to collect logs from different sources and transform them, and Kibana is a Graphical User Interface where a developer can search the logs as they need. Alternatively, you can use Splunk or any other opensource framework for centralizing and analyzing the logs.
Resiliency Implementation: As I said earlier, in a microservice architecture, many microservices are involved to complete a business functionality. It is very common that one of the services is not responding, which will stop the whole flow. To handle such a scenario, resiliency is of the utmost importance, and each and every service should implement resiliency to provide a seamless experience to the end user. When a service is not responding for a certain amount of time, there should be a fallback path so users are not waiting for the response, but are immediately notified about the internal problem with a default response. It is the essence of a responsive design.
Conclusion
When building REST-based microservices, think about two perspectives:
User experience.
Developer perspective.
A user does not like to wait and s/he needs a clear, non-technical message about what is going wrong if an internal problem occurs, so s/he can communicate with the help desk properly. On the other hand, when it's time for support for the microservice, we need the all-important information in the log, as the incident has already happened, and based on the log, we analyze it. Always think about the support perspective while developing a microservice so you can track a flow and get sufficient information from a log.
Published at DZone with permission of Shamik Mitra, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments