|
| 1 | +# Fixing Connection Reset Errors - Usage Guide |
| 2 | + |
| 3 | +## Problem Description |
| 4 | + |
| 5 | +When using Spring AI Alibaba with DashScope (or other AI providers), you may encounter the following error after your application has been idle for a while: |
| 6 | + |
| 7 | +``` |
| 8 | +org.springframework.web.reactive.function.client.WebClientRequestException: Connection reset |
| 9 | +Caused by: java.net.SocketException: Connection reset |
| 10 | +``` |
| 11 | + |
| 12 | +This typically happens in the following scenario: |
| 13 | +1. Your application makes its first API call successfully |
| 14 | +2. The application becomes idle (no API calls for a period of time) |
| 15 | +3. The next API call fails with "Connection reset" |
| 16 | + |
| 17 | +## Root Cause |
| 18 | + |
| 19 | +The issue occurs because: |
| 20 | +1. Spring AI's DashScope integration uses Spring WebFlux's WebClient with Reactor Netty |
| 21 | +2. Reactor Netty maintains a connection pool to reuse HTTP connections |
| 22 | +3. When connections are idle, the server (dashscope.aliyuncs.com) may close them after its own timeout |
| 23 | +4. When your application tries to reuse these closed connections, it gets a "Connection reset" error |
| 24 | + |
| 25 | +## Solution |
| 26 | + |
| 27 | +Use the `spring-ai-alibaba-starter-webclient-config` starter which automatically configures WebClient with proper connection pool management. |
| 28 | + |
| 29 | +### Step 1: Add Dependency |
| 30 | + |
| 31 | +Add this dependency to your `pom.xml`: |
| 32 | + |
| 33 | +```xml |
| 34 | +<dependency> |
| 35 | + <groupId>com.alibaba.cloud.ai</groupId> |
| 36 | + <artifactId>spring-ai-alibaba-starter-webclient-config</artifactId> |
| 37 | +</dependency> |
| 38 | +``` |
| 39 | + |
| 40 | +For Gradle: |
| 41 | + |
| 42 | +```gradle |
| 43 | +implementation 'com.alibaba.cloud.ai:spring-ai-alibaba-starter-webclient-config' |
| 44 | +``` |
| 45 | + |
| 46 | +### Step 2: That's It! |
| 47 | + |
| 48 | +The starter will automatically configure WebClient with the following optimizations: |
| 49 | +- **Idle connection eviction**: Removes connections that have been idle for 30 seconds (default) |
| 50 | +- **Background cleanup**: Periodically scans and removes stale connections every 10 seconds |
| 51 | +- **Connection lifetime limit**: Replaces connections after 5 minutes |
| 52 | +- **Connection validation**: Validates connections before reuse |
| 53 | + |
| 54 | +### Step 3: (Optional) Customize Configuration |
| 55 | + |
| 56 | +You can customize the connection pool settings in your `application.yml`: |
| 57 | + |
| 58 | +```yaml |
| 59 | +spring: |
| 60 | + ai: |
| 61 | + alibaba: |
| 62 | + webclient: |
| 63 | + enabled: true |
| 64 | + max-connections: 500 # Maximum connections per host |
| 65 | + max-idle-time: 30s # Remove connections idle for this long |
| 66 | + max-life-time: 5m # Replace connections after this time |
| 67 | + eviction-interval: 10s # Scan for stale connections every X seconds |
| 68 | +``` |
| 69 | +
|
| 70 | +Or in `application.properties`: |
| 71 | + |
| 72 | +```properties |
| 73 | +spring.ai.alibaba.webclient.enabled=true |
| 74 | +spring.ai.alibaba.webclient.max-connections=500 |
| 75 | +spring.ai.alibaba.webclient.max-idle-time=30s |
| 76 | +spring.ai.alibaba.webclient.max-life-time=5m |
| 77 | +spring.ai.alibaba.webclient.eviction-interval=10s |
| 78 | +``` |
| 79 | + |
| 80 | +## Configuration Properties |
| 81 | + |
| 82 | +| Property | Default | Description | |
| 83 | +|----------|---------|-------------| |
| 84 | +| `max-idle-time` | `30s` | **Most important setting** - Connections idle longer than this are removed. Should be less than the server's idle timeout | |
| 85 | +| `eviction-interval` | `10s` | How often to scan for and remove idle connections | |
| 86 | +| `max-life-time` | `5m` | Maximum time a connection can exist, regardless of use | |
| 87 | +| `max-connections` | `500` | Maximum number of connections per host | |
| 88 | + |
| 89 | +## Tuning Recommendations |
| 90 | + |
| 91 | +### If you still see connection reset errors: |
| 92 | + |
| 93 | +1. **Reduce `max-idle-time`**: Try `15s` or `20s` if the server closes connections quickly |
| 94 | + ```yaml |
| 95 | + spring.ai.alibaba.webclient.max-idle-time: 15s |
| 96 | + ``` |
| 97 | + |
| 98 | +2. **Increase `eviction-interval` frequency**: Scan more frequently for stale connections |
| 99 | + ```yaml |
| 100 | + spring.ai.alibaba.webclient.eviction-interval: 5s |
| 101 | + ``` |
| 102 | + |
| 103 | +### For high-traffic applications: |
| 104 | + |
| 105 | +1. **Increase `max-connections`**: Support more concurrent requests |
| 106 | + ```yaml |
| 107 | + spring.ai.alibaba.webclient.max-connections: 1000 |
| 108 | + ``` |
| 109 | + |
| 110 | +2. **Increase `max-life-time`**: Keep connections longer if they're frequently reused |
| 111 | + ```yaml |
| 112 | + spring.ai.alibaba.webclient.max-life-time: 10m |
| 113 | + ``` |
| 114 | + |
| 115 | +### For low-traffic applications: |
| 116 | + |
| 117 | +1. **Decrease `max-idle-time`**: Remove idle connections more aggressively |
| 118 | + ```yaml |
| 119 | + spring.ai.alibaba.webclient.max-idle-time: 15s |
| 120 | + ``` |
| 121 | + |
| 122 | +2. **Reduce `max-connections`**: Save resources |
| 123 | + ```yaml |
| 124 | + spring.ai.alibaba.webclient.max-connections: 100 |
| 125 | + ``` |
| 126 | + |
| 127 | +## Verification |
| 128 | + |
| 129 | +After adding the starter, you should see a log message like this at startup: |
| 130 | + |
| 131 | +``` |
| 132 | +INFO com.alibaba.cloud.ai.autoconfigure.webclient.WebClientAutoConfiguration - Configuring WebClient with connection pool settings: maxConnections=500, maxIdleTime=PT30S, maxLifeTime=PT5M, evictionInterval=PT10S |
| 133 | +``` |
| 134 | + |
| 135 | +## Disabling |
| 136 | + |
| 137 | +If you need to disable this configuration for any reason: |
| 138 | + |
| 139 | +```yaml |
| 140 | +spring: |
| 141 | + ai: |
| 142 | + alibaba: |
| 143 | + webclient: |
| 144 | + enabled: false |
| 145 | +``` |
| 146 | + |
| 147 | +## How It Works Internally |
| 148 | + |
| 149 | +The starter provides a `WebClient.Builder` bean that Spring AI's DashScope integration automatically uses. This builder is configured with a custom `ConnectionProvider` from Reactor Netty that: |
| 150 | + |
| 151 | +1. **Evicts idle connections**: Checks connection idle time and removes connections that exceed `max-idle-time` |
| 152 | +2. **Background eviction**: Runs a background task every `eviction-interval` to proactively clean up stale connections |
| 153 | +3. **Connection lifetime management**: Ensures no connection lives longer than `max-life-time` |
| 154 | +4. **Proper pooling**: Maintains a pool of up to `max-connections` connections per host |
| 155 | + |
| 156 | +This prevents the application from ever attempting to reuse a connection that the server has already closed. |
| 157 | + |
| 158 | +## Additional Resources |
| 159 | + |
| 160 | +- [Spring AI Documentation](https://docs.spring.io/spring-ai/reference/) |
| 161 | +- [Reactor Netty Connection Pool Documentation](https://projectreactor.io/docs/netty/release/reference/index.html#_connection_pool) |
| 162 | +- [Spring AI Alibaba Documentation](https://java2ai.com) |
0 commit comments