This project is a .NET Dapr application designed to test message delivery and resilience using Azure Service Bus. It acts as both a publisher (sending orders) and a subscriber (receiving orders), with features for controlled publishing concurrency and configurable deterministic message failures.
Messages not successfully processed by the application will be retried by Dapr and Azure Service Bus, eventually moving to a Dead Letter Queue (DLQ) if retries are exhausted.
This quickstart is adapted from the official Dapr pub/sub quickstart for C# SDK
-
.NET 8 SDK: For local development.
-
Dapr CLI: For local Dapr integration.
-
Kubernetes Cluster: With Dapr installed, for K8s deployment.
-
Azure Service Bus: An existing Service Bus Namespace and a queue
- Get your Service Bus Connection String:
- Update
components/pubsub.yaml
: Replacevalue: "secret value"
with your Service Bus connection string.
# components/pubsub.yaml (excerpt - update this part) metadata: name: orderpubsub spec: type: pubsub.azure.servicebus.queues version: v1 metadata: - name: connectionString value: "<YOUR_SERVICE_BUS_CONNECTION_STRING>" # REPLACE THIS
Ensure
components/subscribe.yaml
aligns with your Service Bus configuration# components/subscribe.yaml (excerpt) apiVersion: dapr.io/v2alpha1 kind: Subscription metadata: name: orders-subscription spec: topic: orders routes: default: /orders pubsubname: orderpubsub deadLetterTopic: dead-letter-orders # Messages that exhaust retries will go here.
-
Go to the project folder:
cd order-processor
-
Build & Restore (first time or after code changes):
dotnet restore dotnet build
-
Run Scenarios with Dapr:
MESSAGE_COUNT=100 SUBSCRIBER_FAIL_RATE=0.0 MAX_CONCURRENT_PUBLISHES=5 \ dapr run --app-id order-processor --log-level debug --resources-path ../components --app-port 7006 -- dotnet run
MESSAGE_COUNT=100 SUBSCRIBER_FAIL_RATE=0.1 MAX_CONCURRENT_PUBLISHES=5 \ dapr run --app-id order-processor --log-level debug --resources-path ../components --app-port 7006 -- dotnet run
MESSAGE_COUNT
: Total messages.SUBSCRIBER_FAIL_RATE
: % of messages to intentionally fail (e.g.,0.1
for 10%).MAX_CONCURRENT_PUBLISHES
: Limits concurrent message sends.
-
Stop: Press
Ctrl+C
.
-
Apply K8s Manifests: Apply the Dapr component, subscription, and application deployment to your cluster.
kubectl apply -f components/ kubectl apply -f deployment.yaml
This applies
pubsub.yaml
andsubscribe.yaml
(fromcomponents/
) anddeployment.yaml
. -
Check Logs in K8s: When running in Kubernetes, you'll see output from both your application container and the Dapr sidecar.
- Application logs: Show what your .NET app is doing (publishing, receiving, failing).
- Dapr sidecar logs (
daprd
): Provide detailed information on Dapr's internal operations, such as message routing, retries, and interactions with Service Bus. Use these to diagnose connectivity issues or Dapr's handling of failed messages.
kubectl logs deployments/sb-debug -f # Application logs (app ID from deployment.yaml) kubectl logs deployments/sb-debug -c daprd -f # Dapr sidecar logs
-
Check Service Bus Dead-Letter Queue (DLQ): After running with
SUBSCRIBER_FAIL_RATE > 0
, inspect the DLQ via the Azure portal for your Service Bus queue.az servicebus queue show \ --resource-group <YOUR_RG_GROUP>\ --namespace-name <NS_MAME>> \ --name orders \ --query countDetails.deadLetterMessageCount
- Delete K8s Resources:
kubectl delete -f deployment.yaml kubectl delete -f components/subscribe.yaml kubectl delete -f components/pubsub.yaml
Successful Run (No Failures). SUBSCRIBER_FAIL_RATE=0.0
--- Subscriber received count: 100/100 ---
--- MESSAGE DELIVERY REPORT ---
Total messages attempted to publish: 100
Total messages successfully received: 100
All messages accounted for. No message loss detected.
-------------------------------
Run with Failures Enabled SUBSCRIBER_FAIL_RATE=0.5
--- MESSAGE DELIVERY REPORT ---
Total messages attempted to publish: 10
Total messages successfully received: 5
!!! MESSAGE LOSS DETECTED !!!
Number of lost messages: 5
Lost Order IDs: [1, 2, 3, 4, 5]
-------------------------------