Hello everyone! I recently had the opportunity to explore Dapr. Since Dapr is still in its early stages, there are fewer resources on the internet, especially for Dapr with Node js. In this blog series, I will explain Dapr, its building blocks, and how to integrate Dapr with Node.js.
No prior knowledge of Dapr is required, since this series is user-friendly for beginners. But a little bit of experience with Express.js is needed because we'll be using it in the following blogs.
What is Dapr ?
Dapr is an event-driven, portable runtime for developing cloud and edge microservices. It employs a companion container or process to provide the building blocks required by distributed applications, such as state management, service discovery, reliable messaging, observability, and others.
In simple terms, Dapr is a process that runs independently and provides APIs for all of the building blocks required to build microservices, allowing developers to focus solely on writing business logic in their preferred language.
What Problems does Dapr Solve?
The most difficult problems in microservices. development are always resilient, service invocation, pubsub, and on-demand scaling. Frameworks such as Spring Boot and Nestjs are extremely useful when developing distributed microservices architectures. But they have strong opinions and are strongly tied to specific programming languages. DAPR abstracts all of the above problems from the developer by providing out-of-the-box solutions while also providing flexibility by using a component model that decouples technology choices from your code, making it agnostic to the hosting environment and enabling application portability.
Consider doing PUBSUB as an example of a requirement for your services. Typically, you create code that is targeted at a message broker like Redis Streams. Contrastingly, Dapr comes with publish and subscribe functionality out of the box. Your service calls the Dapr publish and subscribe building blocks, which uses a YAML file for Dapr component configuration to dynamically bind to a publish and subscribe component. Several pre-built message brokers, including redis Streams, NATS Streaming, Azure Service Bus, and GCP pub/sub, are included with Dapr. Using this architecture, your service handed off publish and subscribe to the DAPR runtime. There isn't an SDK, library, or direct reference to the underlying component in your service. Redis can even be changed to any message broker.
Flexibility is Everywhere
Since Dapr follows the SideCar architecture ( which we will be discussing later), it brings flexibility in many ways, like
- Dapr is independent of programming languages and its frameworks.
- We can access DAPR sidecar URLs in HTTP or GRPc.
- Dapr is not vendor locked in, which means Dapr can be deployed to any cloud infrastructure.
- Many building blocks. For example, in state management for storing data, we can choose the database from AWS DynamoDB, Azure CosmosDB, Azure SQL Server, GCP Firebase, PostgreSQL, or Redis, among others.
- Your service's particular message broker or database can be configured as a Dapr component at runtime and is pluggable. By doing this, you free your service from dependency, which increases its portability and adaptability to changes.
Dapr Sidecar Architecture
Dapr's building blocks and components are exposed via a sidecar architecture. Dapr can run in a separate memory process or container alongside your service using a sidecar. Because they are not part of the service but are connected to it, sidecars provide isolation and encapsulation. Because of this separation, each can have its own runtime environment and be built on different programming platforms.
Note Sidecar is the name given to this pattern because it resembles a sidecar attached to a motorcycle.
Each of these building blocks APIs is independent, so you can use any, all, or none of them in your application. These are the following building blocks available:
To access all the building blocks, SDKs are available in all languages. You can use Dapr sidecar URLs directly. We will discuss every building block implementation with examples in upcoming blogs.
Dapr stores the state of actors and stateful services in configurable state stores. Redis is the default local state store, but Dapr can accept other stores, including on-cluster stores. There is also a growing list of community-contributed supported state stores, such as Azure Cosmos DB, Cassandra, Firestore, Memcached, MongoDB, ZooKeeper, and many more.
Dapr provides at-least-once message delivery by default and configures Redis Streams as the messaging backbone for reliable messaging. But we can choose any message broker like Kafka or RabbitMQ.
Your application can communicate with other applications using the standard gRPC or HTTP protocols using service invocation.
Many microservice-based applications require multiple services to communicate with one another. This inter-service communication necessitates that application developers address issues such as service discovery, standardising API calls between services and implementing observability and tracing. Dapr addresses these issues by providing a service invocation API that functions similarly to a reverse proxy and includes built-in service discovery, as well as distributed tracing, metrics, error handling, encryption, and other features.
Dapr uses a sidecar architecture. To invoke an application using Dapr:
- On the Dapr instance, you use the invoke API.
- Each application communicates with its own Dapr instance.
- The Dapr instances find and communicate with one another.
Some other building blocks include resource bindings, actors, observability, secrets, configuration, and distributed locks.
Dapr with Open Source
Dapr is a free and open-source project written in Golang by Microsoft. Dapr integrates with other open source systems and works well with popular open source solutions. The Dapr runtime is built on proven web frameworks, specifically Fast HTTP. While running on Kubernetes, Dapr injects itself as a sidecar container. Dapr sidecars coexist well with service mesh sidecars; Dapr uses OpenTelemetry as the default tracing solution; and so on. Dapr is intended to function as a hub for building blocks. It was never intended to be a self-contained framework that shipped everything from scratch. This design enables Dapr to quickly surface new capabilities to developers. It also enables the community to add new capabilities to the ecosystem, thereby empowering even more service developers.
Installation of Dapr
To install Dapr locally, first you have to install Dapr CLI. The Dapr CLI will be your primary tool for performing Dapr-related tasks. You can find CLI binaries from here. After installing Dapr CLI, you can run the command
dapr. Then, you will see something like this
To install Dapr, you need docker because locally dapr sidecar binaries are only installed. Other components like Redis (state store and pusbsub) and Zipkin (observability) are installed as docker instances.
Now run the command
dapr init will
- Fetch and install the Dapr sidecar binaries locally.
- A Redis container instance is running to serve as a local state store and message broker.
- For observability, a Zipkin container instance is running.
- Create a default components folder with the above component definitions.
- For local actor support, a Dapr placement service container instance is running.
To verify the Dapr installation run
which shows something like this
CLI version: 1.8.1 Runtime version: 1.8.4
Now you can even check Docker instances that are created by Dapr if you run
This shows the default instance created by Dapr
Finally, Dapr comes with a dapr dashboard that runs on port 8080 which will have all the information about microservices that run with Dapr.
That's the introduction to Dapr. You can read more about it at Dapr docs. In the next blog, we will discuss service invocation with Express.js in detail.