Skip to content

Commit 1a9398d

Browse files
Copilotsaragluna
andcommitted
Add documentation for ServiceBus Binder retry configuration
- Updated CHANGELOG.md for both ServiceBus binder and integration modules - Created comprehensive RETRY_CONFIGURATION.md guide - Documented configuration properties, behavior, examples, and best practices Co-authored-by: saragluna <31124698+saragluna@users.noreply.github.com>
1 parent f2c1549 commit 1a9398d

3 files changed

Lines changed: 167 additions & 0 deletions

File tree

sdk/spring/spring-cloud-azure-stream-binder-servicebus/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Added support for Spring Cloud Stream's consumer retry properties (`maxAttempts`, `backOffInitialInterval`, `backOffMaxInterval`, `backOffMultiplier`) to enable automatic retry with exponential backoff for message processing failures.
8+
79
### Breaking Changes
810

911
### Bugs Fixed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# ServiceBus Binder Retry Configuration
2+
3+
## Overview
4+
5+
The ServiceBus Binder now supports Spring Cloud Stream's consumer retry properties, enabling automatic retry with exponential backoff for message processing failures.
6+
7+
## Configuration
8+
9+
You can configure retry behavior using the following properties in your `application.yml` or `application.properties`:
10+
11+
### YAML Configuration Example
12+
13+
```yaml
14+
spring:
15+
cloud:
16+
stream:
17+
bindings:
18+
consumer-in-0:
19+
destination: my-queue
20+
group: my-group
21+
consumer:
22+
max-attempts: 5 # Maximum number of retry attempts (default: 3)
23+
back-off-initial-interval: 1000 # Initial backoff interval in milliseconds (default: 1000)
24+
back-off-max-interval: 10000 # Maximum backoff interval in milliseconds (default: 10000)
25+
back-off-multiplier: 2.0 # Backoff multiplier (default: 2.0)
26+
binders:
27+
servicebus:
28+
type: servicebus
29+
```
30+
31+
### Properties Configuration Example
32+
33+
```properties
34+
spring.cloud.stream.bindings.consumer-in-0.destination=my-queue
35+
spring.cloud.stream.bindings.consumer-in-0.group=my-group
36+
spring.cloud.stream.bindings.consumer-in-0.consumer.max-attempts=5
37+
spring.cloud.stream.bindings.consumer-in-0.consumer.back-off-initial-interval=1000
38+
spring.cloud.stream.bindings.consumer-in-0.consumer.back-off-max-interval=10000
39+
spring.cloud.stream.bindings.consumer-in-0.consumer.back-off-multiplier=2.0
40+
```
41+
42+
## How It Works
43+
44+
### Retry Behavior
45+
46+
When a message processing fails (throws an exception), the binder will:
47+
48+
1. **Retry Automatically**: Retry processing the message based on the `max-attempts` setting
49+
2. **Exponential Backoff**: Wait between retries using an exponential backoff strategy:
50+
- First retry: waits `back-off-initial-interval` milliseconds
51+
- Subsequent retries: wait time is multiplied by `back-off-multiplier`
52+
- Maximum wait: capped at `back-off-max-interval` milliseconds
53+
54+
### Example Retry Timeline
55+
56+
With the configuration above (`max-attempts: 5`, `back-off-initial-interval: 1000`, `back-off-multiplier: 2.0`, `back-off-max-interval: 10000`):
57+
58+
- **Attempt 1**: Initial processing (fails)
59+
- **Wait**: 1000ms (1 second)
60+
- **Attempt 2**: Retry 1 (fails)
61+
- **Wait**: 2000ms (2 seconds) = 1000ms × 2.0
62+
- **Attempt 3**: Retry 2 (fails)
63+
- **Wait**: 4000ms (4 seconds) = 2000ms × 2.0
64+
- **Attempt 4**: Retry 3 (fails)
65+
- **Wait**: 8000ms (8 seconds) = 4000ms × 2.0
66+
- **Attempt 5**: Retry 4 (final attempt, fails)
67+
- **Result**: Message is sent to error channel or dead letter queue (if configured)
68+
69+
### After All Retries Exhausted
70+
71+
When all retry attempts are exhausted:
72+
73+
- If `requeue-rejected: false` (default), the message is **abandoned**
74+
- If `requeue-rejected: true`, the message is sent to the **dead letter queue**
75+
76+
## Consumer Example
77+
78+
```java
79+
@Bean
80+
public Consumer<Message<String>> consumer() {
81+
return message -> {
82+
// This method will be automatically retried if it throws an exception
83+
processMessage(message.getPayload());
84+
};
85+
}
86+
87+
private void processMessage(String payload) {
88+
// Your business logic here
89+
// If this throws an exception, the message will be retried
90+
if (shouldFail(payload)) {
91+
throw new RuntimeException("Processing failed");
92+
}
93+
// Successfully processed
94+
}
95+
```
96+
97+
## Dead Letter Queue Configuration
98+
99+
To send failed messages to the dead letter queue after all retries are exhausted:
100+
101+
```yaml
102+
spring:
103+
cloud:
104+
stream:
105+
servicebus:
106+
bindings:
107+
consumer-in-0:
108+
consumer:
109+
requeue-rejected: true # Send failed messages to DLQ
110+
```
111+
112+
## Disabling Retry
113+
114+
To disable retry (process message only once), set `max-attempts` to 1:
115+
116+
```yaml
117+
spring:
118+
cloud:
119+
stream:
120+
bindings:
121+
consumer-in-0:
122+
consumer:
123+
max-attempts: 1 # No retries
124+
```
125+
126+
## Best Practices
127+
128+
1. **Choose Appropriate Max Attempts**: Consider the nature of your failures. Transient network issues might benefit from more retries, while business logic errors might not.
129+
130+
2. **Configure Realistic Backoff Intervals**: Ensure your backoff intervals are appropriate for your use case:
131+
- Too short: May overwhelm downstream services
132+
- Too long: May delay message processing unnecessarily
133+
134+
3. **Monitor Dead Letter Queues**: Set up monitoring and alerting for messages in the DLQ to handle persistent failures.
135+
136+
4. **Use Specific Exception Types**: Consider catching specific exceptions in your consumer and only retrying for transient errors.
137+
138+
5. **Test Your Configuration**: Use integration tests to verify your retry configuration works as expected.
139+
140+
## Troubleshooting
141+
142+
### Retries Not Working
143+
144+
- Verify `max-attempts` is greater than 1
145+
- Check that exceptions are being thrown from your consumer
146+
- Enable debug logging: `logging.level.org.springframework.retry=DEBUG`
147+
148+
### Too Many Retries
149+
150+
- Reduce `max-attempts`
151+
- Increase `back-off-initial-interval` or reduce `back-off-multiplier`
152+
- Consider implementing circuit breaker patterns for persistent failures
153+
154+
### Messages Going to DLQ Immediately
155+
156+
- Verify `requeue-rejected` is set correctly
157+
- Check if `max-attempts` is set to 1
158+
- Review error handling logic in your consumer
159+
160+
## Related Configuration
161+
162+
- [Spring Cloud Stream Binding Properties](https://docs.spring.io/spring-cloud-stream/docs/current/reference/html/spring-cloud-stream.html#_consumer_properties)
163+
- [Azure Service Bus Error Handling](https://learn.microsoft.com/azure/service-bus-messaging/service-bus-dead-letter-queues)

sdk/spring/spring-integration-azure-servicebus/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
### Features Added
66

7+
- Added `setRetryTemplate` method to `ServiceBusInboundChannelAdapter` to support configurable retry logic for message processing.
8+
79
### Breaking Changes
810

911
### Bugs Fixed

0 commit comments

Comments
 (0)