Quickstart: Service-to-component resiliency

Get started with Dapr’s resiliency capabilities via the state management API

Observe Dapr resiliency capabilities by simulating a system failure. In this Quickstart, you will:

  • Execute a microservice application that continuously persists and retrieves state via Dapr’s state management API.
  • Trigger resiliency policies by simulating a system failure.
  • Resolve the failure and the microservice application will resume.

Diagram showing the resiliency applied to Dapr APIs

Select your preferred language-specific Dapr SDK before proceeding with the Quickstart.

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

  1. git clone https://github.com/dapr/quickstarts.git

In a terminal window, navigate to the order-processor directory.

  1. cd ../state_management/python/sdk/order-processor

Install dependencies

  1. pip3 install -r requirements.txt

Step 2: Run the application

Run the order-processor service alongside a Dapr sidecar. The Dapr sidecar then loads the resiliency spec located in the resources directory:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Resiliency
  3. metadata:
  4. name: myresiliency
  5. scopes:
  6. - checkout
  7. spec:
  8. policies:
  9. retries:
  10. retryForever:
  11. policy: constant
  12. maxInterval: 5s
  13. maxRetries: -1
  14. circuitBreakers:
  15. simpleCB:
  16. maxRequests: 1
  17. timeout: 5s
  18. trip: consecutiveFailures >= 5
  19. targets:
  20. apps:
  21. order-processor:
  22. retry: retryForever
  23. circuitBreaker: simpleCB
  1. dapr run --app-id order-processor --resources-path ../../../resources/ -- python3

Once the application has started, the order-processorservice writes and reads orderId key/value pairs to the statestore Redis instance defined in the statestore.yaml component.

  1. == APP == Saving Order: { orderId: '1' }
  2. == APP == Getting Order: { orderId: '1' }
  3. == APP == Saving Order: { orderId: '2' }
  4. == APP == Getting Order: { orderId: '2' }
  5. == APP == Saving Order: { orderId: '3' }
  6. == APP == Getting Order: { orderId: '3' }
  7. == APP == Saving Order: { orderId: '4' }
  8. == APP == Getting Order: { orderId: '4' }

Step 3: Introduce a fault

Simulate a fault by stopping the Redis container instance that was initialized when executing dapr init on your development machine. Once the instance is stopped, write and read operations from the order-processor service begin to fail.

Since the resiliency.yaml spec defines statestore as a component target, all failed requests will apply retry and circuit breaker policies:

  1. targets:
  2. components:
  3. statestore:
  4. outbound:
  5. retry: retryForever
  6. circuitBreaker: simpleCB

In a new terminal window, run the following command to stop Redis:

  1. docker stop dapr_redis

Once Redis is stopped, the requests begin to fail and the retry policy titled retryForever is applied. The output below shows the logs from the order-processor service:

  1. INFO[0006] Error processing operation component[statestore] output. Retrying...

As per the retryForever policy, retries will continue for each failed request indefinitely, in 5 second intervals.

  1. retryForever:
  2. policy: constant
  3. maxInterval: 5s
  4. maxRetries: -1

Once 5 consecutive retries have failed, the circuit breaker policy, simpleCB, is tripped and the breaker opens, halting all requests:

  1. INFO[0026] Circuit breaker "simpleCB-statestore" changed state from closed to open
  1. circuitBreakers:
  2. simpleCB:
  3. maxRequests: 1
  4. timeout: 5s
  5. trip: consecutiveFailures >= 5

After 5 seconds has surpassed, the circuit breaker will switch to a half-open state, allowing one request through to verify if the fault has been resolved. If the request continues to fail, the circuit will trip back to the open state.

  1. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  2. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from half-open to open
  3. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  4. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from half-open to closed

This half-open/open behavior will continue for as long as the Redis container is stopped.

Step 3: Remove the fault

Once you restart the Redis container on your machine, the application will recover seamlessly, picking up where it left off.

  1. docker start dapr_redis
  1. INFO[0036] Recovered processing operation component[statestore] output.
  2. == APP == Saving Order: { orderId: '5' }
  3. == APP == Getting Order: { orderId: '5' }
  4. == APP == Saving Order: { orderId: '6' }
  5. == APP == Getting Order: { orderId: '6' }
  6. == APP == Saving Order: { orderId: '7' }
  7. == APP == Getting Order: { orderId: '7' }
  8. == APP == Saving Order: { orderId: '8' }
  9. == APP == Getting Order: { orderId: '8' }
  10. == APP == Saving Order: { orderId: '9' }
  11. == APP == Getting Order: { orderId: '9' }

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

  1. git clone https://github.com/dapr/quickstarts.git

In a terminal window, navigate to the order-processor directory.

  1. cd ../state_management/javascript/sdk/order-processor

Install dependencies

  1. npm install

Step 2: Run the application

Run the order-processor service alongside a Dapr sidecar. The Dapr sidecar then loads the resiliency spec located in the resources directory:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Resiliency
  3. metadata:
  4. name: myresiliency
  5. scopes:
  6. - checkout
  7. spec:
  8. policies:
  9. retries:
  10. retryForever:
  11. policy: constant
  12. maxInterval: 5s
  13. maxRetries: -1
  14. circuitBreakers:
  15. simpleCB:
  16. maxRequests: 1
  17. timeout: 5s
  18. trip: consecutiveFailures >= 5
  19. targets:
  20. apps:
  21. order-processor:
  22. retry: retryForever
  23. circuitBreaker: simpleCB
  1. dapr run --app-id order-processor --resources-path ../../../resources/ -- npm start

Once the application has started, the order-processorservice writes and reads orderId key/value pairs to the statestore Redis instance defined in the statestore.yaml component.

  1. == APP == Saving Order: { orderId: '1' }
  2. == APP == Getting Order: { orderId: '1' }
  3. == APP == Saving Order: { orderId: '2' }
  4. == APP == Getting Order: { orderId: '2' }
  5. == APP == Saving Order: { orderId: '3' }
  6. == APP == Getting Order: { orderId: '3' }
  7. == APP == Saving Order: { orderId: '4' }
  8. == APP == Getting Order: { orderId: '4' }

Step 3: Introduce a fault

Simulate a fault by stopping the Redis container instance that was initialized when executing dapr init on your development machine. Once the instance is stopped, write and read operations from the order-processor service begin to fail.

Since the resiliency.yaml spec defines statestore as a component target, all failed requests will apply retry and circuit breaker policies:

  1. targets:
  2. components:
  3. statestore:
  4. outbound:
  5. retry: retryForever
  6. circuitBreaker: simpleCB

In a new terminal window, run the following command to stop Redis:

  1. docker stop dapr_redis

Once Redis is stopped, the requests begin to fail and the retry policy titled retryForever is applied. The output below shows the logs from the order-processor service:

  1. INFO[0006] Error processing operation component[statestore] output. Retrying...

As per the retryForever policy, retries will continue for each failed request indefinitely, in 5 second intervals.

  1. retryForever:
  2. policy: constant
  3. maxInterval: 5s
  4. maxRetries: -1

Once 5 consecutive retries have failed, the circuit breaker policy, simpleCB, is tripped and the breaker opens, halting all requests:

  1. INFO[0026] Circuit breaker "simpleCB-statestore" changed state from closed to open
  1. circuitBreakers:
  2. simpleCB:
  3. maxRequests: 1
  4. timeout: 5s
  5. trip: consecutiveFailures >= 5

After 5 seconds has surpassed, the circuit breaker will switch to a half-open state, allowing one request through to verify if the fault has been resolved. If the request continues to fail, the circuit will trip back to the open state.

  1. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  2. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from half-open to open
  3. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  4. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from half-open to closed

This half-open/open behavior will continue for as long as the Redis container is stopped.

Step 3: Remove the fault

Once you restart the Redis container on your machine, the application will recover seamlessly, picking up where it left off.

  1. docker start dapr_redis
  1. INFO[0036] Recovered processing operation component[statestore] output.
  2. == APP == Saving Order: { orderId: '5' }
  3. == APP == Getting Order: { orderId: '5' }
  4. == APP == Saving Order: { orderId: '6' }
  5. == APP == Getting Order: { orderId: '6' }
  6. == APP == Saving Order: { orderId: '7' }
  7. == APP == Getting Order: { orderId: '7' }
  8. == APP == Saving Order: { orderId: '8' }
  9. == APP == Getting Order: { orderId: '8' }
  10. == APP == Saving Order: { orderId: '9' }
  11. == APP == Getting Order: { orderId: '9' }

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

  1. git clone https://github.com/dapr/quickstarts.git

In a terminal window, navigate to the order-processor directory.

  1. cd ../state_management/csharp/sdk/order-processor

Install dependencies

  1. dotnet restore
  2. dotnet build

Step 2: Run the application

Run the order-processor service alongside a Dapr sidecar. The Dapr sidecar then loads the resiliency spec located in the resources directory:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Resiliency
  3. metadata:
  4. name: myresiliency
  5. scopes:
  6. - checkout
  7. spec:
  8. policies:
  9. retries:
  10. retryForever:
  11. policy: constant
  12. maxInterval: 5s
  13. maxRetries: -1
  14. circuitBreakers:
  15. simpleCB:
  16. maxRequests: 1
  17. timeout: 5s
  18. trip: consecutiveFailures >= 5
  19. targets:
  20. apps:
  21. order-processor:
  22. retry: retryForever
  23. circuitBreaker: simpleCB
  1. dapr run --app-id order-processor --resources-path ../../../resources/ -- dotnet run

Once the application has started, the order-processorservice writes and reads orderId key/value pairs to the statestore Redis instance defined in the statestore.yaml component.

  1. == APP == Saving Order: { orderId: '1' }
  2. == APP == Getting Order: { orderId: '1' }
  3. == APP == Saving Order: { orderId: '2' }
  4. == APP == Getting Order: { orderId: '2' }
  5. == APP == Saving Order: { orderId: '3' }
  6. == APP == Getting Order: { orderId: '3' }
  7. == APP == Saving Order: { orderId: '4' }
  8. == APP == Getting Order: { orderId: '4' }

Step 3: Introduce a fault

Simulate a fault by stopping the Redis container instance that was initialized when executing dapr init on your development machine. Once the instance is stopped, write and read operations from the order-processor service begin to fail.

Since the resiliency.yaml spec defines statestore as a component target, all failed requests will apply retry and circuit breaker policies:

  1. targets:
  2. components:
  3. statestore:
  4. outbound:
  5. retry: retryForever
  6. circuitBreaker: simpleCB

In a new terminal window, run the following command to stop Redis:

  1. docker stop dapr_redis

Once Redis is stopped, the requests begin to fail and the retry policy titled retryForever is applied. The output below shows the logs from the order-processor service:

  1. INFO[0006] Error processing operation component[statestore] output. Retrying...

As per the retryForever policy, retries will continue for each failed request indefinitely, in 5 second intervals.

  1. retryForever:
  2. policy: constant
  3. maxInterval: 5s
  4. maxRetries: -1

Once 5 consecutive retries have failed, the circuit breaker policy, simpleCB, is tripped and the breaker opens, halting all requests:

  1. INFO[0026] Circuit breaker "simpleCB-statestore" changed state from closed to open
  1. circuitBreakers:
  2. simpleCB:
  3. maxRequests: 1
  4. timeout: 5s
  5. trip: consecutiveFailures >= 5

After 5 seconds has surpassed, the circuit breaker will switch to a half-open state, allowing one request through to verify if the fault has been resolved. If the request continues to fail, the circuit will trip back to the open state.

  1. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  2. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from half-open to open
  3. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  4. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from half-open to closed

This half-open/open behavior will continue for as long as the Redis container is stopped.

Step 3: Remove the fault

Once you restart the Redis container on your machine, the application will recover seamlessly, picking up where it left off.

  1. docker start dapr_redis
  1. INFO[0036] Recovered processing operation component[statestore] output.
  2. == APP == Saving Order: { orderId: '5' }
  3. == APP == Getting Order: { orderId: '5' }
  4. == APP == Saving Order: { orderId: '6' }
  5. == APP == Getting Order: { orderId: '6' }
  6. == APP == Saving Order: { orderId: '7' }
  7. == APP == Getting Order: { orderId: '7' }
  8. == APP == Saving Order: { orderId: '8' }
  9. == APP == Getting Order: { orderId: '8' }
  10. == APP == Saving Order: { orderId: '9' }
  11. == APP == Getting Order: { orderId: '9' }

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

  1. git clone https://github.com/dapr/quickstarts.git

In a terminal window, navigate to the order-processor directory.

  1. cd ../state_management/java/sdk/order-processor

Install dependencies

  1. mvn clean install

Step 2: Run the application

Run the order-processor service alongside a Dapr sidecar. The Dapr sidecar then loads the resiliency spec located in the resources directory:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Resiliency
  3. metadata:
  4. name: myresiliency
  5. scopes:
  6. - checkout
  7. spec:
  8. policies:
  9. retries:
  10. retryForever:
  11. policy: constant
  12. maxInterval: 5s
  13. maxRetries: -1
  14. circuitBreakers:
  15. simpleCB:
  16. maxRequests: 1
  17. timeout: 5s
  18. trip: consecutiveFailures >= 5
  19. targets:
  20. apps:
  21. order-processor:
  22. retry: retryForever
  23. circuitBreaker: simpleCB
  1. dapr run --app-id order-processor --resources-path ../../../resources/ -- java -jar target/OrderProcessingService-0.0.1-SNAPSHOT.jar

Once the application has started, the order-processorservice writes and reads orderId key/value pairs to the statestore Redis instance defined in the statestore.yaml component.

  1. == APP == Saving Order: { orderId: '1' }
  2. == APP == Getting Order: { orderId: '1' }
  3. == APP == Saving Order: { orderId: '2' }
  4. == APP == Getting Order: { orderId: '2' }
  5. == APP == Saving Order: { orderId: '3' }
  6. == APP == Getting Order: { orderId: '3' }
  7. == APP == Saving Order: { orderId: '4' }
  8. == APP == Getting Order: { orderId: '4' }

Step 3: Introduce a fault

Simulate a fault by stopping the Redis container instance that was initialized when executing dapr init on your development machine. Once the instance is stopped, write and read operations from the order-processor service begin to fail.

Since the resiliency.yaml spec defines statestore as a component target, all failed requests will apply retry and circuit breaker policies:

  1. targets:
  2. components:
  3. statestore:
  4. outbound:
  5. retry: retryForever
  6. circuitBreaker: simpleCB

In a new terminal window, run the following command to stop Redis:

  1. docker stop dapr_redis

Once Redis is stopped, the requests begin to fail and the retry policy titled retryForever is applied. The output below shows the logs from the order-processor service:

  1. INFO[0006] Error processing operation component[statestore] output. Retrying...

As per the retryForever policy, retries will continue for each failed request indefinitely, in 5 second intervals.

  1. retryForever:
  2. policy: constant
  3. maxInterval: 5s
  4. maxRetries: -1

Once 5 consecutive retries have failed, the circuit breaker policy, simpleCB, is tripped and the breaker opens, halting all requests:

  1. INFO[0026] Circuit breaker "simpleCB-statestore" changed state from closed to open
  1. circuitBreakers:
  2. simpleCB:
  3. maxRequests: 1
  4. timeout: 5s
  5. trip: consecutiveFailures >= 5

After 5 seconds has surpassed, the circuit breaker will switch to a half-open state, allowing one request through to verify if the fault has been resolved. If the request continues to fail, the circuit will trip back to the open state.

  1. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  2. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from half-open to open
  3. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  4. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from half-open to closed

This half-open/open behavior will continue for as long as the Redis container is stopped.

Step 3: Remove the fault

Once you restart the Redis container on your machine, the application will recover seamlessly, picking up where it left off.

  1. docker start dapr_redis
  1. INFO[0036] Recovered processing operation component[statestore] output.
  2. == APP == Saving Order: { orderId: '5' }
  3. == APP == Getting Order: { orderId: '5' }
  4. == APP == Saving Order: { orderId: '6' }
  5. == APP == Getting Order: { orderId: '6' }
  6. == APP == Saving Order: { orderId: '7' }
  7. == APP == Getting Order: { orderId: '7' }
  8. == APP == Saving Order: { orderId: '8' }
  9. == APP == Getting Order: { orderId: '8' }
  10. == APP == Saving Order: { orderId: '9' }
  11. == APP == Getting Order: { orderId: '9' }

Pre-requisites

For this example, you will need:

Step 1: Set up the environment

Clone the sample provided in the Quickstarts repo.

  1. git clone https://github.com/dapr/quickstarts.git

In a terminal window, navigate to the order-processor directory.

  1. cd ../state_management/go/sdk/order-processor

Install dependencies

  1. go build .

Step 2: Run the application

Run the order-processor service alongside a Dapr sidecar. The Dapr sidecar then loads the resiliency spec located in the resources directory:

  1. apiVersion: dapr.io/v1alpha1
  2. kind: Resiliency
  3. metadata:
  4. name: myresiliency
  5. scopes:
  6. - checkout
  7. spec:
  8. policies:
  9. retries:
  10. retryForever:
  11. policy: constant
  12. maxInterval: 5s
  13. maxRetries: -1
  14. circuitBreakers:
  15. simpleCB:
  16. maxRequests: 1
  17. timeout: 5s
  18. trip: consecutiveFailures >= 5
  19. targets:
  20. apps:
  21. order-processor:
  22. retry: retryForever
  23. circuitBreaker: simpleCB
  1. dapr run --app-id order-processor --resources-path ../../../resources -- go run .

Once the application has started, the order-processorservice writes and reads orderId key/value pairs to the statestore Redis instance defined in the statestore.yaml component.

  1. == APP == Saving Order: { orderId: '1' }
  2. == APP == Getting Order: { orderId: '1' }
  3. == APP == Saving Order: { orderId: '2' }
  4. == APP == Getting Order: { orderId: '2' }
  5. == APP == Saving Order: { orderId: '3' }
  6. == APP == Getting Order: { orderId: '3' }
  7. == APP == Saving Order: { orderId: '4' }
  8. == APP == Getting Order: { orderId: '4' }

Step 3: Introduce a fault

Simulate a fault by stopping the Redis container instance that was initialized when executing dapr init on your development machine. Once the instance is stopped, write and read operations from the order-processor service begin to fail.

Since the resiliency.yaml spec defines statestore as a component target, all failed requests will apply retry and circuit breaker policies:

  1. targets:
  2. components:
  3. statestore:
  4. outbound:
  5. retry: retryForever
  6. circuitBreaker: simpleCB

In a new terminal window, run the following command to stop Redis:

  1. docker stop dapr_redis

Once Redis is stopped, the requests begin to fail and the retry policy titled retryForever is applied. The output belows shows the logs from the order-processor service:

  1. INFO[0006] Error processing operation component[statestore] output. Retrying...

As per the retryForever policy, retries will continue for each failed request indefinitely, in 5 second intervals.

  1. retryForever:
  2. policy: constant
  3. maxInterval: 5s
  4. maxRetries: -1

Once 5 consecutive retries have failed, the circuit breaker policy, simpleCB, is tripped and the breaker opens, halting all requests:

  1. INFO[0026] Circuit breaker "simpleCB-statestore" changed state from closed to open
  1. circuitBreakers:
  2. simpleCB:
  3. maxRequests: 1
  4. timeout: 5s
  5. trip: consecutiveFailures >= 5

After 5 seconds has surpassed, the circuit breaker will switch to a half-open state, allowing one request through to verify if the fault has been resolved. If the request continues to fail, the circuit will trip back to the open state.

  1. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  2. INFO[0031] Circuit breaker "simpleCB-statestore" changed state from half-open to open
  3. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from open to half-open
  4. INFO[0036] Circuit breaker "simpleCB-statestore" changed state from half-open to closed

This half-open/open behavior will continue for as long as the Redis container is stopped.

Step 3: Remove the fault

Once you restart the Redis container on your machine, the application will recover seamlessly, picking up where it left off.

  1. docker start dapr_redis
  1. INFO[0036] Recovered processing operation component[statestore] output.
  2. == APP == Saving Order: { orderId: '5' }
  3. == APP == Getting Order: { orderId: '5' }
  4. == APP == Saving Order: { orderId: '6' }
  5. == APP == Getting Order: { orderId: '6' }
  6. == APP == Saving Order: { orderId: '7' }
  7. == APP == Getting Order: { orderId: '7' }
  8. == APP == Saving Order: { orderId: '8' }
  9. == APP == Getting Order: { orderId: '8' }
  10. == APP == Saving Order: { orderId: '9' }
  11. == APP == Getting Order: { orderId: '9' }

Tell us what you think!

We’re continuously working to improve our Quickstart examples and value your feedback. Did you find this quickstart helpful? Do you have suggestions for improvement?

Join the discussion in our discord channel.

Next steps

Learn more about the resiliency feature and how it works with Dapr’s building block APIs.

Explore Dapr tutorials >>

Last modified October 12, 2023: Update config.toml (#3826) (0ffc2e7)