Dapr doesn’t actually manage your microservices; it provides a sidecar that enhances them with distributed system capabilities.
Let’s see Dapr in action. Imagine two simple microservices: a frontend that calls an order-processor service.
order-processor (Python)
from flask import Flask, request, jsonify
import os
app = Flask(__name__)
@app.route('/process', methods=['POST'])
def process_order():
data = request.json
order_id = data.get('orderId')
print(f"Received order {order_id} for processing.")
# Simulate some work
return jsonify({"status": "processed", "orderId": order_id}), 200
if __name__ == '__main__':
app.run(port=5000)
frontend (Node.js)
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;
app.use(express.json());
app.post('/submit-order', async (req, res) => {
const orderData = req.body;
console.log(`Frontend received order: ${JSON.stringify(orderData)}`);
try {
// Dapr will route this to the order-processor service
const daprUrl = `http://localhost:3500/v1.0/invoke/order-processor/method/process`;
const response = await axios.post(daprUrl, orderData);
console.log('Order processed:', response.data);
res.json({ message: 'Order submitted successfully!', ...response.data });
} catch (error) {
console.error('Error processing order:', error.message);
res.status(500).json({ message: 'Failed to submit order.' });
}
});
app.listen(port, () => {
console.log(`Frontend app listening at http://localhost:${port}`);
});
Now, let’s integrate Dapr.
First, install Dapr CLI and initialize Dapr locally:
dapr init -k # Initializes Dapr for Kubernetes
Next, deploy Dapr to your AKS cluster. This typically involves applying the Dapr control plane components:
kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/master/charts/dapr/crds/dapr.io.yaml
kubectl apply -f https://raw.githubusercontent.com/dapr/dapr/master/charts/dapr/dapr.yaml
(Note: For production, you’d use Helm charts for better management).
Now, let’s run our microservices with Dapr sidecars. Instead of running python app.py and node app.js, we’ll use dapr run.
Running order-processor with Dapr:
dapr run --app-id order-processor --dapr-http-port 3500 --app-port 5000 python order_processor.py
--app-id order-processor: This is the unique name Dapr uses to identify this service.--dapr-http-port 3500: The port Dapr listens on for API calls from other services.--app-port 5000: The port your actual application listens on.
Running frontend with Dapr:
dapr run --app-id frontend --dapr-http-port 3500 --app-port 3000 node app.js
Now, from your frontend application, you can send a request. If you are running these locally, you’d curl your frontend app:
curl -X POST -H "Content-Type: application/json" -d '{"orderId": "12345"}' http://localhost:3000/submit-order
The frontend application, running with Dapr, makes a request to http://localhost:3500/v1.0/invoke/order-processor/method/process. Dapr intercepts this, looks up the service with app-id order-processor, and forwards the request to its actual running instance (port 5000 in this case). The order-processor service receives the request, processes it, and sends a response back through Dapr to the frontend.
This illustrates Dapr’s core function: service invocation. It abstracts away network concerns, service discovery, and retries. You just call http://localhost:3500/v1.0/invoke/TARGET_APP_ID/method/TARGET_METHOD, and Dapr handles the rest.
The mental model of Dapr is that it’s a sidecar pattern. Your application runs in its own container, and a Dapr sidecar runs alongside it in a separate container within the same pod (in Kubernetes) or on the same host (locally). Your application communicates with its local Dapr sidecar over HTTP or gRPC. The Dapr sidecar then communicates with other Dapr sidecars across the network. This separation allows Dapr to add capabilities without modifying your application code.
Dapr provides a rich set of building blocks beyond just service invocation:
- State Management: Persist and retrieve application state using components like Redis or Cosmos DB, without writing direct database logic.
- Publish/Subscribe: Decouple services by publishing events to a message broker (like Kafka or RabbitMQ) and having other services subscribe to them, again via Dapr components.
- Bindings: Trigger your services from external systems (like Cron jobs or queues) or send data to external systems.
- Secrets Management: Securely retrieve secrets from providers like Azure Key Vault or HashiCorp Vault.
When you deploy your services to AKS, you’ll typically create Kubernetes deployments for your application containers and then use Dapr’s Kubernetes integration to automatically inject the Dapr sidecar into your application pods. This is often done via annotations on your deployment’s pod template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend-deployment
spec:
replicas: 1
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
annotations:
dapr.io/enabled: "true"
dapr.io/app-id: "frontend"
dapr.io/app-port: "3000" # Port your app listens on
spec:
containers:
- name: frontend
image: your-frontend-image:latest
ports:
- containerPort: 3000
When Kubernetes schedules this pod, Dapr’s injector (which is part of the Dapr control plane deployed earlier) will see the annotations and automatically add a second container to the pod: the Dapr sidecar. Your application container will then communicate with localhost:3500 (or its configured Dapr HTTP port) within the pod.
The most surprising thing about Dapr’s service invocation is that the dapr.io/app-port annotation doesn’t have to match the port your application is actually listening on. Dapr’s sidecar will attempt to connect to the specified app-port on localhost. If your application is listening on, say, port 8080, but you set dapr.io/app-port: "3000", Dapr will try to talk to port 3000. Your application must be listening on the port specified in dapr.io/app-port for Dapr to successfully forward requests to it. It’s a direct mapping of Dapr’s expectation to your app’s reality.
The next step is to explore Dapr’s state management building block.