Why Microservice Platform for CAKE?
Organization wide adoption at Sysco Labs to Microservice based product offerings is an important architectural decision. It plays a key role in helping us face the challenges of maintaining several mature products that need scalability within multiple contexts and include scalability in processing, storage, delivery of product features, and in teams.
Some of the features that were developed as a part of a monolithic app started to stretch beyond the scalability we had initially. The natural choice for us was to move them into a Microservices model. One example is the storage of printed receipts that started to consume 60% of our data storage which was useful only occasionally. Therefore, designing a Microservice around this helped us scale our applications in the most optimal way.
As Sysco Labs grew, teams started to specialize in certain domains or lines of business, and wanted to bring their work to production as independent entities, without having to depend on other teams, all while keeping the existing applications unaffected. In the Microservices model, we broke away the Wallet functionality and Menu services to their own silos of business, making it possible for teams to move as independently as possible when bringing their release to production.
Considering such situations, we found that Microservices makes a lot of sense for our teams – it makes us more productive and helps us design and implement more scalable solutions.
Microservice Vs APIs.
It’s important to distinguish Microservices from generic APIs as it may sound that Microservice is yet another API. Though it’s true that it is another API, there are some distinguishable attributes in Microservices that makes it a useful pattern for scalable architectures.
Attributes of Microservice
- Cohesive Functionality – Each service should provide a cohesive and a useful functionality. If the services are too fine-grained, it may become a maintenance and integration nightmare. Therefore, when designing Microservices, it’s important to find the right boundary for the API definitions and ensure that each Microservice adds a distinct business value as an independent service or a unit.
- A Small, Clean Codebase – One of the key attributes of a Microservice API is to keep the functionality small, focused, and simple. That attribute makes it possible to easily understand the functionality and the implementation, as well as to maintain the service with maximum efficiency. A well-engineered code also provides fast iterations, refactoring, and promotes the evolution of these small code bases.
- Private Data – Having shared data across many services or APIs makes tight coupling between them and prohibits smooth evolution of the individual APIs. When data is encapsulated within the service, its possible to evolve the API and data together as a unit without having to bother about how the outside world is affected by the changes to the data.
- Minimal Integrations, Loosely Coupled – It’s important to keep each service as independent as possible, but sometimes, we may also need to integrate it with other APIs to get certain tasks done. The tighter the integrations with other systems, the harder it would be to understand and maintain it. Asynchronous and message based communication can be useful to minimize the coupling to a certain level in an integrated environment.
- Independently Deployable – Being able to deploy independently means more productivity. One of the core attributes of Microservices architecture is to be able to deploy the services independently, making it possible to roll out changes without affecting the existing clients. Having a well-defined versioning pattern is required to keep the clients compatible and to provide a smooth migration to the desired version of the service.
- Stateless and Self-Bootable – A Microservice should be able to boot itself into a valid state at anytime without having tight dependencies to other services or to past data. Microservices should be able to scale out horizontally at all times based on processing needs. It is recommended to avoid having a locally stored state such as local file stores, local db, and caching. Instead, store any state in centrally managed data stores to ensure any state is consistently shared between load balanced and auto scaling setup.
These attributes of Microservices play a vital role to ensure proper implementation of a Microservice Architecture.
Essential Building Blocks of Microservices
- Guidelines and Governance
When many teams start implementing Microservices independently, there is a good chance that teams will adopt multiple approaches to similar problems. Inconsistencies in end point definitions, documentation, terminologies, and duplication of functionality are common problems that can be resulted in the absence of having proper guidelines and governance. Governance helps to ensure that the teams adhere to the guidelines set forth, ensuring consistency across Microservices. It’s important that the guidelines and governance model does not make the teams under productive. Their purpose is to increase their own efficiency so that there is a natural adoption to follow the guidelines.
- API Gateway
There are many well known functionalities required in APIs such as Security, Authentication, Authorization, Caching, Logging, Transformation, Proxying, etc. Having an API gateway becomes essential to minimize the rework and to improve efficiency in implementing these well-known requirements.
- Micro Service Documentation
Proper and consistent documentation of the APIs is important as all of your applications will be designed around them. Without documentation, the services would be useless. Documentation should be precise, concise, and consistent across multiple APIs while using agreed upon terminology based on domain, so that clients can easily interpret the functionality of the service. It is important to make the API documentations available in a single location so that clients can discover the documentations easily and visualize the relationship of each API in a holistic manner.
- Configuration Management
Since Microservices can be deployed in many environments or in auto scaling infrastructure, the service configurations cannot be stored statically. Instead, configurations should be loaded dynamically based on the environment it runs as and when the services are spawned. It is recommended not to store configurations in the source code or in locally available file locations as it makes it impossible to deploy the API in an auto-scaling infrastructure. The Microservice should be designed in a way that the same build can run in multiple configurations without having to be rebuilt.
- Networking Infrastructure
With Microservices architecture, there will be many more APIs being developed/deployed by independent teams. The networking infrastructure/architecture should provide sufficient security, performance, and reliability to deploy, operate, and monitor services.
- Deployment Strategy
Deployment strategy plays a vital role in Microservices architecture as having a smooth and consistent deployment strategy makes it possible for teams to iterate over multiple services at a much faster pace with a higher level of confidence.
The services should not assume any dependencies to be available, instead all the dependencies should be explicitly provided upfront. Containerization is a great way to ensure the services have everything it needs when running. Containerization also helps to deploy solutions in a variety of Container Services such as Docker, AWS BeanStalk, Google`s Kubenetes, etc.
- Release Management
Releases should be organized in such a way that the gaps between production and pre-production is minimal, making it a breeze to take releases to production. Minimize the gap between (human, time, or runtime) production and pre-production.
Reduce the Human Gap by letting teams manage the entire lifecycle of the services such as development, deployment, monitoring, and evolving. Having end-to-end visibility of the Microservices helps teams architect the solution better and have minimum operational overheads.
The Time Gap between pre-production and production should also be minimized such that changes could be rolled out more frequently. Attributes of Microservices such as focused functionality, small code base, etc. are complementary to moving the developed code into production with the lowest time gap.
Having a similar runtime environment in any environment that the service is deployed helps reduce the Runtime Gap. Containerization helps ensure that the services have everything it needs to run.
With Microservices, it`s desirable to let teams manage the services throughout its lifespan instead of having different teams for testing, deployment, monitoring, etc. Such a model also helps the team to fix any operational or non-functional pain point comparatively faster. Attributes of Microservices are complementary to adopt an effective dev-ops model without burdening the team.
As teams undertake the ownership of the Microservices end to end, they need more autonomy in terms of deployment, configurations, and the monitoring of production deploys. Teams need to extend their full stack capabilities beyond the mere development of services to providing support for entire the lifecycle of the service as well.
Since teams will have to own multiple services, and continuous changes to the existing API are expected, having consistency in how the team develops Microservices greatly helps reduce the learning curve and increase productivity over time. Therefore, adopting a uniform technology stack and well-standardized frameworks makes a lots of sense.
Operational support is the responsibility of the team who owns the Microservice. Automated monitoring of application and infrastructure health is a must to relieve the additional burden on the team.
Log aggregation becomes mandatory as the Microservices are spawned in unknown instances in an auto scaling setup, leaving no immediate trace where to look for logs. There could be an agent pushing the logs to a centrally managed aggregation service that provides up to date log data in a more organized way.
Once you have the basic and the necessary building blocks in place, scaling the application in multiple fold is a breeze.
The teams will be able to get their work to production at a much better frequency, increasing the overall productivity.
Microservices architecture will help implement an effective dev-ops model, allowing you to reap the benefits of a dev-ops world of operational support.
There are a variety of cloud solutions available such as AWS, BeanStalk, ECS, Kubenets from Google, and Azure that can be used to deploy the services and let it auto scale.
https://12factor.net/ provides a clean approach to developing applications that can easily adopt to a Microservices Platform
http://semver.org/ provides a standard versioning approach that could be used in a Microservices Platform
https://getkong.org/about/ is becoming increasingly popular as a Microservices API gateway due to its simplicity and stability of nginx.
http://projects.spring.io/spring-cloud/ provides lots of building blocks required in a Microservices Platform
https://projects.spring.io/spring-boot/ is a Microservices development framework from spring
https://www.npmjs.com/package/micro is a Microservices development framework in node.js
– Some container management services that will help deploy and manage Microservices
http://swagger.io/ -Open source standard for Restful API documentation