What are Microservices?
Microservices are an architectural approach emerging from service-oriented architecture. The approach emphasizes self-management and light weight as the means to improve software agility, scalability, velocity, and team autonomy. In essence, microservices are an approach to solution decomposition as described in the AKF Scale Cube..
The approach decomposes or disintegrates an application into multiple services. Each microservice should be:
- independently deployed (or capable of independent deployment)
- independently executable (not dependent on another service for execution)
- an “owner” of some unique business capability
- owned by a single team (no two teams own a microservice
- an owner of its own data store and ideally the only solution accessing that store
The approach logically simplifies a software-centric understanding of business capabilities.
Figure 1 shows a sample application using microservices.
Size of a Microservice
Generally, the term “micro” is an unfortunate one as teams tend to misread it as meaning “a small number of lines of code” or “single task”. To help answer the sizing question, we’ve put together a list of considerations based on developer throughput, availability, scalability, and cost. By considering these, you can decide if your service should be comparatively large or small in lines of code, objects/methods, functions, etc, or split up into smaller, individual services and swim lanes. Put another way, consider “micro” as a comparison to a singular, monolith or “macro” solution.
Splitting too aggressively can be overly costly and have little return for the effort involved. Companies with little to no growth will be better served to focus their resources on developing a marketable product than by fine-tuning their service sizes using the considerations below.
See the full article here.
The illustration below can be used to quickly determine the size (in functionality) of any given service.
Figure 2 - Determine Service Size
Loose coupling is an essential characteristic of microservices. Any microservice should be capable of independent deployment. There must be zero coordination necessary for the deployment with other microservices, and other teams. This loose coupling enables frequent and rapid deployments, decreasing time to market for value creation within a product.
Each microservice is scaled by running multiple instances of it as in the X axis of the AKF Scale Cube. There are many processes to handle, and memory and CPU requirements are an important consideration when assessing the cost of operation of the entire system. Container technologies are often employed to aid with ease of deployment. Traditional Java EE stacks are less desirable for microservices from this point of view because they are optimized for running a single application container, not a multitude of containers. Node.js and Go are more common as they are more lightweight and require less memory and CPU power per instance.
In theory, it is possible to create a microservice system in which each service uses a different language and stack (polyglot implementations). Such a polyglot implementation has many advantages and disadvantages. Generally speaking, in smaller companies economy of scale, code reuse, and developer skills all set an upper bound on this number of no more than 2 to 3 “stacks”.
Benefits of Microservices
As software increases in complexity, the ability to separate functional areas in what would otherwise be a monolith into sets of independent services can yield many benefits, which include, but are not limited to the following:
- More efficient debugging – no more jumping through multiple layers of an application, in essence, better fault isolation
- Accelerated software delivery – smaller, easier to understand code bases owned by a single team increase velocity as a result of lower communication and coordination overhead
- Scalability – microservices lend themselves to be integrated with other applications or services via industry-standard interfaces such as REST and can be scaled independently relative to their individual request rates
- Fault tolerance – reduced downtime due to more resilient services< assuming that proper fault isolation and bulkheads are in place/li>
- Reusability – as microservices are organized around business cases and not a particular project, due to their implementation, they can be reused and easily slotted into other projects or services, thereby reducing costs.
- Deployment – as everything is encapsulated into separate microservices, you only need to deploy the services that you‘ve changed and not the entire application. A key tenet of microservice development is ensuring that each service is loosely coupled with existing services as mentioned earlier.
- Polyglot – each service could be developed in its own language, and run on its own infrastructure and runtime stack. This allows teams to diversify to maximize the opportunity to tap a markets skill sets or to operate across various geographies where each geography may have unique talent and skills
Challenges of Microservice Architecture
As with any architecture, microservices come with certain concerns and risks. Put another way, the approach is not a panacea.
- Too many coding languages – yes, we listed this as a benefit, but it can also be a double-edged sword. Too many languages, in the end, could make your solution unwieldy and potentially difficult to maintain.
- Integration – you need to make a conscious effort to ensure your services as are loosely coupled as they possibly can be (yes, mentioned earlier too), otherwise, if you don‘t, you‘ll make a change to one service which has a ripple effect with additional services thereby making service integration difficult and time-consuming.
- Integration test – testing one monolithic system can be simpler as everything is in “one solution”, whereas a solution based on microservices architecture may have components that live on other systems and/or environments thereby making it harder to configure an “end to end” test environment.
- Communication – microservices naturally need to interact with other services, each service will depend on a specific set of inputs and return specific outputs, these communication channel‘s need to be defined into specific interfaces standards and shared with your team. Failures between microservices can occur when interface definitions haven‘t been adhered to which can result in lost time.
- Unique Failures - microservices can introduce unique failure modes such as deadlock when multiple services and data stores are aggregated. Race conditions are also a more common problem with the propagation of services. Teams need to take great care to think through these possibilities when defining service boundaries.
- Multiplicative Effect of Failure - Deployment architectures are important for microservices, as chaining services together will cause a multiplicative effect of failure that reduces downtime. When developing deployment architectures, choose services in breadth and libraries for depth to increase availability and reduce failure probability. Peruse our patterns and anti-patterns list for a better understanding of what to do and what not to do with microservices.
Don’t even think about Microservices without DevOps
Microservices allow you to respond quickly and incrementally to business opportunities. Incremental and more frequent delivery of new capabilities drives the need for organizations to adopt DevOps practices.
Microservices cause an explosion of moving parts. It is not a good idea to attempt to implement microservices without serious deployment and monitoring automation. You should be able to push a button and get your app deployed. In fact, you should not even do anything. Committing code should get your app deployed through the commit hooks that trigger the delivery pipelines in at least development. You still need some manual checks and balances for deploying into production.
You no longer just have a single release team to build, deploy, and test your application. Microservices architecture results in more frequent and greater numbers of smaller applications being deployed.
DevOps is what enables you to do more frequent deployments and to scale to handle the growing number of new teams releasing microservices. DevOps is a prerequisite to being able to successfully adopt microservices at scale in your organization.
Teams that have not yet adopted DevOps must invest significantly in defining release processes and corresponding automation and tools. This is what enables you to onboard new service teams and achieve efficient release and testing of microservices. Without it, each microservice team must create its own DevOps infrastructure and services, which results in higher development costs. It also means inconsistent levels of quality, security, and availability of microservices across teams.
As you begin to reorganize teams to align with business components and services, also consider creating microservices DevOps teams who provide the cross-functional development teams with tool support, dependency tracking, governance, and visibility into all microservices. This provides business and technical stakeholders greater visibility into microservices investment and delivery as microservices move through their lifecycle.
The DevOps services team provides the needed visibility across the teams as to what services are being deployed, used by other teams, and ultimately used by client applications. This loosely coupled approach provides greater business agility.
Frequent releases keep applications relevant to business needs and priorities. Smaller releases means less code changes, and that helps reduce risk significantly. With smaller release cycles, it is easier to detect bugs much earlier in the development lifecycle and to gain quick feedback from the user base. All these are characteristics of a well-oiled microservices enterprise.
AKF Partners has helped to architect some of the most scalable, highly available, fault-tolerant and fastest response time solutions on the internet. Give us a call - we can help.