Over the last decade, there has been a huge shift away from heavily coded monolithic applications to finer, self-contained microservices. However, while Microservice-based systems boast advantages such as agility and independent scalability, they also come with inherent challenges such as service invocation, distributed transactions, secrets management, and message broker integration to name a few.
Dapr, the Distributed Application Runtime, aims to solve the above challenges and more, by allowing developers to focus on their core application/business logic, without having to worry about solving the challenges of building a distributed system.
In this article, we’ll take a closer look at the technology behind Dapr, and explore the key components and capabilities that make it a leading tool for working with distributed applications.
What is Dapr?
Dapr is a portable, serverless, event-driven runtime that enables developers to easily build resilient, stateless, and stateful microservices that run on the cloud and edge using their language and framework of choice. Dapr runs natively on Kubernetes, as a self-hosted binary on a designated machine or IoT device, or as a container that can be injected into any system, in the cloud or on-premises.
The project was initiated and announced by Microsoft on October 16, 2019, however, Dapr is not owned by Microsoft and is being incubated at the Cloud Native Computing Foundation (CNCF). It is currently available as an open-source project on GitHub.
How does Dapr work?
Dapr works by using the sidecar pattern (a secondary piece of software that is deployed alongside the primary application) using HTTP or gRPC APIs to communicate with the application code. This enables Dapr to support all existing and future programming languages without requiring users to import frameworks or libraries.
In essence, Dapr helps reduce the inherent complexity of distributed microservice applications by codifying industry best practices into APIs (building blocks) that offer common distributed application capabilities: state management, service-to-service invocation, pub/sub messaging, secrets management, and observability.
What are the key capabilities of Dapr?
As we mentioned above, Dapr provides seven modular building blocks that provide common best practices for building microservices. Each building block is fully independent, meaning that developers can choose to use one, some, or all blocks depending on application requirements.
Dapr building blocks are pluggable and opt-in, so cloud-native developers can choose only the functionality they need. They provide the functionality to build resilient, event-driven, and stateful distributed applications without the complexity of manual implementation.
Let’s take a closer look at each:
- Service-to-Service Invocation
Within a distributed system, one service must be able to communicate with another to complete specific operations, which often involve complex challenges such as service location and security, handling retries in the event of transient errors, or capturing insights across service call graphs to diagnose production issues.
The Dapr service invocation building block can help streamline the communication between services by using a sidecar as a reverse proxy for the intended service. For example, let’s say “Service A” needs to communicate a request to “Service B.” Using the Service Invocation API, Dapr will create a sidecar for both Service A and B, which will communicate the request and executed function on behalf of the services, eliminating the complexity of making direct calls.
- Publish & Subscribe
The Publish-Subscribe (pub/sub) pattern is a messaging pattern commonly used by architects in distributed applications. However, implementing this pattern is often complex due to feature differences across different messaging products.
The Dapr Publish-Subscribe building block simplifies pub/sub functionality by using loose coupling, also known as temporal decoupling, wherein the pattern decouples publishers (services that send messages) from subscribers (services that consume messages). With this pattern, both publishers and subscribers rely on a centralized, pluggable message broker to distribute the messages, removing dependency from the service while increasing portability and flexibility.
- Secrets Management
Keeping secrets at safe distance from the code is a standard requirement and best practice. However, accessing secret stores can be quite complex, particularly within multi-cloud scenarios involving multiple different vendor-specific secret stores.
With Dapr’s dedicated secrets management building block, developers are able to easily and securely store secrets and reference them in the configuration file from other Dapr components such as Kubernetes, Azure KeyVault, AWS Secrets Manager, etc. All access is secured through authentication and authorization, ensuring that only applications with sufficient credentials have access to secrets.
- Resource Bindings
Resource bindings are where the event-driven nature of Dapr really shines. Using this building block, users are able to trigger the app with events coming in from external systems, or interface with external systems. Essentially, the bindings building block enables developers to focus on business logic, rather than on the implementation details of interacting with a system.
For example, the API eliminates the need to write boilerplate code for connecting to and polling from messaging systems such as queues and message buses. Additionally, it allows users to keep their code free from SDKs or libraries, handle retries and failure recovery, switch between bindings at runtime, and build portable applications with environment-specific bindings set up and no required code changes.
- State Management
When it comes to tracking state in a distributed application, developers face numerous challenges: the use of different data store types, varied consistency levels to access and update data, conflict resolution, retrying transient errors, etc.
With the Dapr state management building block, developers can easily address these challenges and streamline tracking state without dependencies or contending with a learning curve on third-party storage SDKs. Using state management, the application can store data as key/value pairs in the supported state stores, eliminating the need for stateful or stateless services to support different backends. Dapr offers a variety of state stores that can be plugged through configuration including Redis, Azure CosmosDB, Azure SQL Server, and PostgreSQL.
Actor model implementations are typically connected to a specific language or platform, however, with the Dapr actors building block, developers can easily leverage the actor model from any language or platform.
The virtual actor pattern eliminates the need to explicitly create actors, instead, actors are activated implicitly and placed on a node in the cluster the first time a message is sent to the actor. When not executing operations, actors are silently unloaded from memory. If a node fails, Dapr automatically moves activated actors to healthy nodes. In addition to facilitating messaging between actors, the Dapr actor API also features scheduling capabilities to streamline workflow organization.
When building any application, understanding how the system is behaving is an important part of successful operation. However, observability becomes infinitely more complex in distributed systems comprised of multiple microservices.
With the Dapr observability building block, developers and operators can observe system service and application behavior without having to instrument them. Dapr system components and runtime support metrics, logs, and traces to debug, operate and monitor Dapr system services, components, and user applications, which can then be sent to an OpenTelemetry collector and linked to external monitoring tools for full spectrum visibility.
Is Dapr the right solution for your business?
Most developers would be quick to agree – writing high-performing, scalable and reliable distributed applications is difficult. But Dapr takes the complexity of distributed applications and distills it into easy-to-use, proven patterns and best practices, while allowing cloud-native developers to truly embrace the multilingual nature of microservices to build event-driven, distributed cloud-native applications.
By letting Dapr handle complex challenges such as service discovery, encryption, observability, secret management, bindings, state management, etc., developers can stop worrying about underlying infrastructure components, and keep their focus on what matters – business logic, productivity, and clean, simple code.
How can I learn more?
This article is part of a larger series focusing on the technologies and topics found in the first edition of the TechRadar by Devoteam. To see what our community of tech leaders said about the current position of Dapr in the market, take a look at the most recent edition of the TechRadar by Devoteam