Introduction in Dapr Distributed Application Runtime
Dapr is an open-source, portable, event-driven runtime that makes it easy for developers to build resilient, stateless, and stateful microservices running in the cloud and at the edge, embracing diversity of languages and development frameworks.
Dapr is fully platform and language agnostic; this means it can run on any platform, any Kubernetes deployment, in the cloud or on-premises, and even on IoT (Internet of Things) devices. Dapr focuses on delivering building blocks that make it easier for developers to build microservices, as opposed to a service mesh, which focuses on network-related concerns.
How Dapr works
Communication between multiple microservices requires the use of gRPC (general Remote Procedure Calls), API (Application Programming Interface), pub/sub (publish-subscribe pattern), and more. Additionally, developers also need to handle Service Discovery and State Management. These two scenarios involve different parameters. Depending on whether it's a stateless or stateful app, developers need to work with different SDKs (Software Development Kits) and programming models.
Dapr employs a sidecar pattern similar to the sidecar implementation in service mesh architecture, using a local proxy to route requests. Sidecars in Dapr enable integration of microservice building blocks at runtime rather than compile time. This brings the benefit of Dapr being integrated with existing and legacy code operated through a standard HTTP/gRPC interface, allowing enterprise developers to experience the benefits of microservices development without rewriting their applications.
Dapr concepts
Below are some prominent Dapr concepts aimed at providing a fundamental understanding of Dapr:
Any framework, any language, anywhere: Dapr being fully platform agnostic means you can run applications locally, on any Kubernetes cluster, and other managed environments integrated with Dapr. This empowers developers to build microservice applications running in the cloud and at the edge without altering their code. Dapr consolidates best practices for building microservice applications into open, independent building blocks for developing portable applications with the language and framework of your choice.
Secrets: In Dapr, a secret is any piece of private data you want to protect from unauthorized users. Dapr provides a secrets building block API and integrates it with secret stores like Azure Key Vault and Kubernetes to securely store secrets.
Robust microservice building blocks for cloud and edge: A building block is like an HTTP or gRPC API that can be invoked from user code and utilizes one or more Dapr components.
Dapr consists of a set of building blocks, with the ability to add new building blocks.
Each of these building blocks is independent, and you can use one, several, or all of them in your application. In the initial release of Dapr, the following building blocks are provided:
Service invocation: Service Invocation enables communication between applications via familiar endpoints in the form of HTTP or gRPC messages.
State management: Dapr provides a key-value or stateful API with pluggable state stores for persistence. State management for storing key-value pairs allows for easy development of long-running, highly available stateful services alongside stateless services in your application. The state store is pluggable and can include Azure CosmosDB, AWS DynamoDB, or Redis.
Publish and subscribe messaging: Dapr supports the pub/sub pattern between applications. Pub/Sub is a loosely coupled messaging pattern where publishers publish messages to a topic that subscribers subscribe to.
Resource bindings: Dapr allows triggering external services via the Dapr binding API, enabling your application to be triggered by events sent by the bound service. A binding provides bidirectional connectivity to an external cloud/on-premise service or system.
Actors: An actor is an isolated, independent unit of computation and state with single-threaded execution. Dapr provides extensive capabilities in its actor runtime, including concurrency, state, lifecycle management for activating/deactivating actors, and timers and reminders to wake actors.
Distributed tracing: Distributed tracing collects and aggregates trace events, metrics, and performance data across Dapr instances. It enables you to trace the entire call chain across multiple services or see call metrics on a user service.
Secrets: Service code can invoke the secrets API to fetch secrets from supported secret stores by Dapr. Dapr provides a simple secrets API and integrates with secret stores such as Azure Key Vault and Kubernetes secret stores.
Sidecar architecture
Dapr exposes its APIs as a sidecar architecture, either as a container or as a process without requiring any Dapr runtime code in the application code. This simplifies integration with Dapr from other runtimes and provides separation of application logic for better supportability.
Standalone mode
In standalone mode, Dapr runs as a separate process that your service code can call via HTTP or gRPC.
Kubernetes
In container hosting environments like Kubernetes, Dapr runs as a sidecar container alongside the application container within the same pod.
Hosting environments
Dapr can be run on various hosting platforms. The supported hosting platforms include:
Self-hosted: Dapr runs on a single machine as a process or in a container.
Kubernetes: Dapr runs on any Kubernetes cluster, whether from a cloud provider or on-premises.
Running Dapr on a local development machine in self-hosted mode Dapr can be configured to run on your local developer machine in self-hosted mode. Each running service has a Dapr runtime process or sidecar configured to utilize state stores, pub/sub, binding components, and other building blocks. You can use the Dapr CLI to run a Dapr-enabled application on your local machine.
Running Dapr in Kubernetes mode
Dapr can be configured to run on any Kubernetes cluster. Deploying and running a Dapr-enabled application on your Kubernetes cluster is as simple as adding a few annotations to your deployment schemas. To give your service an ID and port known to Dapr, enable tracing information, and start the Dapr sidecar container, annotate your Kubernetes deployment as follows.
Developer languages, SDKs, and frameworks
Dapr offers language-specific SDKs for Go, .NET, Java, JavaScript, and Python. These SDKs expose the functionality in Dapr building blocks, such as storing state, publishing an event, or creating an actor, through a typed, language API instead of calling the HTTP/gRPC API. And because these SDKs share the Dapr runtime, you get support for cross-language actors and functions.
Development frameworks
Dapr can be integrated with any development framework. For example, in the Dapr .NET SDK, there's integration with ASP.NET Core, which brings stateful routing controllers that respond to pub/sub events from other services. And in the Dapr Java SDK, you'll find integration with Spring Boot.
Components
Dapr uses a modular design where functionality is delivered as a component. Each component has an interface definition. All components are interchangeable, so you can replace one component with another that shares the same interface. You can get a list of currently available components in the current hosting environment using the dapr components CLI command.
Middleware components
Dapr allows custom middleware to be injected into the request processing pipeline. Middleware can perform additional actions on a request, such as authentication, encryption, and message transformation, before routing the request to user code or before returning the request to the client. Middleware components are used with the Service Invocation building block.
Conclusion
Dapr provides best practices for common capabilities in building microservice applications that developers can use and deploy in a standardized way across any environment. Dapr brings some of the demonstrated techniques and best practices to microservices development. In fact, Dapr does for modern cloud-native applications what ODBC (Open Database Connectivity) and JDBC (Java Database Connectivity) did for data-driven client/server applications. TypeScript, C#, Scala, Ruby, and Rust are also slated for SDK development in the near future.