- Source: Microservices
In software engineering, a microservice architecture is an architectural pattern that arranges an application as a collection of loosely coupled, fine-grained services, communicating through lightweight protocols. A microservice-based architecture enables teams to develop and deploy their services independently, reduce code interdependency and increase readability and modularity within a codebase. This is achieved by reducing several dependencies in the codebase, allowing developers to evolve their services with limited restrictions, and reducing additional complexity. Consequently, organizations can develop software with rapid growth and scalability, as well as implement off-the-shelf services more easily. These benefits come with the cost of needing to maintain a decoupled structure within the codebase, which means its initial implementation is more complex than that of a monolithic codebase. Interfaces need to be designed carefully and treated as APIs.
A microservice is analogous to a bounded context in domain-driven design.
Definition
There is no single definition for microservices. A consensus has evolved over time in the industry. Some of the defining characteristics that are frequently cited include:
Services in a microservice architecture are often processes that communicate over a network to fulfill a goal using technology-agnostic protocols such as HTTP.
Services are organized around business capabilities.
Services can be implemented using different programming languages, databases, hardware and software environments, depending on what fits best.
Services are small in size, messaging-enabled, bounded by contexts, autonomously developed, independently deployable, decentralized and built and released with automated processes.
Microservices are a specialization of an implementation approach for service-oriented architectures used to build flexible, independently deployable software systems.
A microservice is not a layer within a monolithic application (for example, the web controller or the backend-for-frontend). Rather, it is a self-contained piece of business functionality with clear interfaces, and may, through its own internal components, implement a layered architecture. From a strategic perspective, microservice architecture essentially follows the Unix philosophy of "Do one thing and do it well". Martin Fowler describes a microservices-based architecture as having the following properties:
Lends itself to a continuous delivery software development process. A change to a small part of the application only requires rebuilding and redeploying only one or a small number of services.
Adheres to principles such as fine-grained interfaces (to independently deployable services), business-driven development (e.g. domain-driven design).
Usage
It is common for microservices architectures to be adopted for cloud-native applications, serverless computing, and applications using lightweight container deployment. According to Fowler, because of the large number (when compared to monolithic application implementations) of services, decentralized continuous delivery and DevOps with holistic service monitoring are necessary to effectively develop, maintain, and operate such applications. A consequence of (and rationale for) following this approach is that the individual microservices can be individually scaled. In the monolithic approach, an application supporting three functions would have to be scaled in its entirety even if only one of these functions had a resource constraint. With microservices, only the microservice supporting the function with resource constraints needs to be scaled out, thus providing resource and cost optimization benefits.
In February 2020, the Cloud Microservices Market Research Report predicted that the global microservice architecture market size will increase at a CAGR of 21.37% from 2019 to 2026 and reach $3.1 billion by 2026.
History
In 1999, software developer Peter Rodgers had been working on the Dexter research project at Hewlett Packard Labs, whose aim was to make code less brittle and to make large-scale, complex software systems robust to change. Ultimately this path of research led to the development of resource-oriented computing (ROC), a generalized computation abstraction in which REST is a special subset. In 2005, during a presentation at the Web Services Edge conference, Rodgers argued for "REST-services" and stated that "Software components are Micro-Web-Services... Micro-Services are composed using Unix-like pipelines (the Web meets Unix = true loose-coupling). Services can call services (+multiple language run-times). Complex service assemblies are abstracted behind simple URI interfaces. Any service, at any granularity, can be exposed." He described how a well-designed microservices platform "applies the underlying architectural principles of the Web and REST services together with Unix-like scheduling and pipelines to provide radical flexibility and improved simplicity in service-oriented architectures.
Also in 2005, Alistair Cockburn wrote about hexagonal architecture which is a software design pattern that is used along with the microservices. This pattern makes the design of the microservice possible since it isolates in layers the business logic from the auxiliary services needed in order to deploy and run the microservice completely independent from others.
Service granularity
A key step in defining a microservice architecture is figuring out how big an individual microservice has to be. There is no consensus or litmus test for this, as the right answer depends on the business and organizational context. For instance, Amazon uses a service-oriented architecture where service often maps 1:1 with a team of 3 to 10 engineers.
To find the right level of service granularity, architects have to continuously iterate their component designs with programmers. Architects need to take into account user requirements, responsibilities, and architectural characteristics (aka non-functional requirements).
In the context of software architecture, services dedicated to a single task, such as calling a specific backend system or performing a particular calculation, are known as atomic services. Services that call atomic services to consolidate an output are referred to as composite services.
It is considered bad practice to make the service too small, as then the runtime overhead and the operational complexity can overwhelm the benefits of the approach. When services become too fine-grained, alternative approaches should be considered, such as packaging the function as a library or integrating it into other microservices.
If domain-driven design is being employed in modeling the domain for which the system is being built, then a microservice could be as small as an aggregate or as large as a bounded Context.
In the granularity of microservices discussion, there is a spectrum. On one end are the Anaemic Services, which do not have a large number of responsibilities, and on the other end are the Modular Monolith, which are large modules of a system.
Benefits
The benefit of decomposing an application into different smaller services are numerous:
Modularity: This makes the application easier to understand, develop, test, and become more resilient to architecture erosion. This benefit is often argued in comparison to the complexity of monolithic architectures.
Scalability: Since microservices are implemented and deployed independently of each other, i.e. they run within independent processes, they can be monitored and scaled independently.
Integration of heterogeneous and legacy systems: microservices are considered a viable means for modernizing existing monolithic software application. There are experience reports of several companies who have successfully replaced parts of their existing software with microservices or are in the process of doing so. The process for software modernization of legacy applications is done using an incremental approach.
Distributed development: it parallelizes development by enabling small autonomous teams to develop, deploy and scale their respective services independently. It also allows the architecture of an individual service to emerge through continuous refactoring. Microservice-based architectures facilitate continuous integration, continuous delivery and deployment.
Criticism and concerns
The microservices approach is subject to criticism for a number of issues:
Services form information barriers.
Inter-service calls over a network have a higher cost in terms of network latency and message processing time than in-process calls within a monolithic service process.
Testing and deployment are more complicated.
Moving responsibilities between services is more difficult. It may involve communication between different teams, rewriting the functionality in another language or fitting it into a different infrastructure. However, microservices can be deployed independently from the rest of the application, while teams working on monoliths need to synchronize to deploy together.
Viewing the size of services as the primary structuring mechanism can lead to too many services when the alternative of internal modularization may lead to a simpler design. This requires understanding the overall architecture of the applications and interdependencies between components.
Two-phased commits are regarded as an anti-pattern in microservices-based architectures, resulting in a tighter coupling of all the participants within the transaction. However, the lack of this technology causes awkward dances which have to be implemented by all the transaction participants in order to maintain data consistency.
Development and support of many services are more challenging if they are built with different tools and technologies - this is especially a problem if engineers move between projects frequently.
The protocol typically used with microservices (HTTP) was designed for public-facing services, and as such is unsuitable for working internal microservices that often must be impeccably reliable.
While not specific to microservices, the decomposition methodology often uses functional decomposition, which does not handle changes in the requirements while still adding the complexity of services.
The very concept of microservice is misleading since there are only services. There is no sound definition of when a service starts or stops being a microservice.
Data aggregation. In order to have a full view of a working system, it is required to extract data sets from the microservices repositories and aggregate them into a single schema. For example, to be able to create operational reports that are not possible using a single microservice repository.
= Complexities
=The architecture introduces additional complexity and new problems to deal with, such as latency, message format design, backup/availability/consistency (BAC), load balancing and fault tolerance. All of these problems have to be addressed at scale. The complexity of a monolithic application does not disappear if it is re-implemented as a set of microservices. Some of the complexity gets translated into operational complexity. Other places where the complexity manifests itself are increased network traffic and resulting in slower performance. Also, an application made up of any number of microservices has a larger number of interface points to access its respective ecosystem, which increases the architectural complexity. Various organizing principles (such as hypermedia as the engine of application state (HATEOAS), interface and data model documentation captured via Swagger, etc.) have been applied to reduce the impact of such additional complexity.
Challenges
Microservices are susceptible to the fallacies of distributed computing, a series of misconceptions that can lead to significant issues in software development and deployment.
Best practices
According to O'Reilly, each microservice should have its own architectural characteristics (a.k.a non functional requirements), and architects should not define uniform characteristics for the entire distributed system.
Latency is often measured through "99th percentile" because median and average latencies can be misleading as they can miss outliers.
Technologies
Computer microservices can be implemented in different programming languages and might use different infrastructures. Therefore, the most important technology choices are the way microservices communicate with each other (synchronous, asynchronous, UI integration) and the protocols used for the communication (RESTful HTTP, messaging, GraphQL ...). In a traditional system, most technology choices like the programming language impact the whole system. Therefore, the approach to choosing technologies is quite different.
The Eclipse Foundation has published a specification for developing microservices, Eclipse MicroProfile.
= Service mesh
=In a service mesh, each service instance is paired with an instance of a reverse proxy server, called a service proxy, sidecar proxy, or sidecar. The service instance and sidecar proxy share a container, and the containers are managed by a container orchestration tool such as Kubernetes, Nomad, Docker Swarm, or DC/OS. The service proxies are responsible for communication with other service instances and can support capabilities such as service (instance) discovery, load balancing, authentication and authorization, secure communications, and others.
In a service mesh, the service instances and their sidecar proxies are said to make up the data plane, which includes not only data management but also request processing and response. The service mesh also includes a control plane for managing the interaction between services, mediated by their sidecar proxies.
= A comparison of platforms
=Implementing a microservice architecture is very difficult. There are many concerns (see table below) that any microservice architecture needs to address. Netflix developed a microservice framework to support their internal applications, and then open-sourced many portions of that framework. Many of these tools have been popularized via the Spring Framework – they have been re-implemented as Spring-based tools under the umbrella of the Spring Cloud project. The table below shows a comparison of an implementing feature from the Kubernetes ecosystem with an equivalent from the Spring Cloud world. One noteworthy aspect of the Spring Cloud ecosystem is that they are all Java-based technologies, whereas Kubernetes is a polyglot runtime platform.
See also
References
Further reading
"Special theme issue on microservices". IEEE Software . 35 (3). May–June 2018.
I. Nadareishvili et al., Microservices Architecture – Aligning Principles, Practices and Culture, O'Reilly, 2016, ISBN 978-1-491-95979-4
S. Newman, Building Microservices – Designing Fine-Grained Systems, O'Reilly, 2015 ISBN 978-1491950357
Wijesuriya, Viraj Brian (2016-08-29) Microservice Architecture, Lecture Notes - University of Colombo School of Computing, Sri Lanka
Christudas Binildas (June 27, 2019). Practical Microservices Architectural Patterns: Event-Based Java Microservices with Spring Boot and Spring Cloud. Apress. ISBN 978-1484245002.
Kata Kunci Pencarian:
- Kotlin (bahasa pemrograman)
- Microservices
- Service-oriented architecture
- GRPC
- Self-contained system (software)
- OwnCloud
- Twelve-Factor App methodology
- Monolithic application
- Hexagonal architecture (software)
- Micro-frontend
- Edge case