Skip to content

Commit 984eb42

Browse files
feat: add timeout and keep alive (#1220)
* feat: add timeout and keep alive params * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent fff99fe commit 984eb42

File tree

6 files changed

+372
-2
lines changed

6 files changed

+372
-2
lines changed

docs_src/src/components/documentation/Navigation.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,10 @@ export const navigation = [
288288
href: '/documentation/en/api_reference/scaling',
289289
title: 'Scaling the Application',
290290
},
291+
{
292+
href: '/documentation/en/api_reference/timeout_configuration',
293+
title: 'Timeout Configuration',
294+
},
291295
{
292296
href: '/documentation/en/api_reference/advanced_features',
293297
title: 'Advanced Features',
@@ -455,6 +459,7 @@ const translations = {
455459
Websockets: 'Websockets',
456460
Exceptions: 'Exceptions',
457461
'Scaling the Application': 'Scaling the Application',
462+
'Timeout Configuration': 'Timeout Configuration',
458463
'Advanced Features': 'Advanced Features',
459464
'Advanced Routing': 'Advanced Routing',
460465
'Architecture Deep Dive': 'Architecture Deep Dive',
@@ -500,6 +505,7 @@ const translations = {
500505
'Server-Sent Events': '服务器发送事件',
501506
'Exceptions': '异常处理',
502507
'Scaling the Application': '多核扩展',
508+
'Timeout Configuration': '超时配置',
503509
'Advanced Features': '高级特性',
504510
'Advanced Routing': '高级路由',
505511
'Architecture Deep Dive': '架构深度剖析',
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
export const description =
2+
'Configure timeout settings to handle high-concurrency scenarios and prevent resource exhaustion.'
3+
4+
# Timeout Configuration
5+
6+
Robyn supports comprehensive timeout configuration to handle high-concurrency scenarios and prevent resource exhaustion like the "Too many open files" error. {{ className: 'lead' }}
7+
8+
## Configuration Options
9+
10+
### Method Parameters
11+
12+
Configure timeouts directly in the `app.start()` method:
13+
14+
```python
15+
from robyn import Robyn
16+
17+
app = Robyn(__file__)
18+
19+
@app.get("/")
20+
async def hello(request):
21+
return "Hello, world!"
22+
23+
# Configure timeout settings
24+
app.start(
25+
host="0.0.0.0",
26+
port=8080,
27+
client_timeout=30, # Client connection timeout (seconds)
28+
keep_alive_timeout=20 # Keep-alive timeout (seconds)
29+
)
30+
```
31+
32+
### Environment Variables
33+
34+
Override configuration using environment variables:
35+
36+
```bash
37+
# Set timeout configurations
38+
export ROBYN_CLIENT_TIMEOUT=45
39+
export ROBYN_KEEP_ALIVE_TIMEOUT=30
40+
41+
# Start your application
42+
python app.py
43+
```
44+
45+
## Configuration Parameters
46+
47+
| Parameter | Default | Description | Environment Variable |
48+
|-----------|---------|-------------|---------------------|
49+
| `client_timeout` | 30 | Maximum time (seconds) for client request processing | `ROBYN_CLIENT_TIMEOUT` |
50+
| `keep_alive_timeout` | 20 | Time (seconds) to keep idle connections alive | `ROBYN_KEEP_ALIVE_TIMEOUT` |
51+
52+
## Usage Examples
53+
54+
### Basic Configuration
55+
56+
```python
57+
# Minimal timeout configuration
58+
app.start(client_timeout=30)
59+
```
60+
61+
### High-Traffic Production Setup
62+
63+
```python
64+
# Optimized for high-traffic scenarios
65+
app.start(
66+
host="0.0.0.0",
67+
port=8080,
68+
client_timeout=60, # Allow longer processing time
69+
keep_alive_timeout=15 # Shorter keep-alive for faster turnover
70+
)
71+
```
72+
73+
### Development Setup
74+
75+
```python
76+
# Development-friendly settings
77+
app.start(
78+
client_timeout=300, # Long timeout for debugging
79+
keep_alive_timeout=60 # Longer keep-alive for testing
80+
)
81+
```
82+
83+
### Load Testing Configuration
84+
85+
```python
86+
# Optimized for load testing with tools like wrk
87+
app.start(
88+
client_timeout=10, # Quick timeouts
89+
keep_alive_timeout=5 # Fast connection turnover
90+
)
91+
```
92+
93+
## Environment Variable Priority
94+
95+
Environment variables take precedence over method parameters:
96+
97+
```python
98+
# This will use ROBYN_CLIENT_TIMEOUT=60 if set, otherwise 30
99+
app.start(client_timeout=30)
100+
```
101+
102+
## Troubleshooting
103+
104+
### "Too Many Open Files" Error
105+
106+
If you encounter file descriptor exhaustion:
107+
108+
1. **Increase system limits:**
109+
```bash
110+
ulimit -n 65536
111+
```
112+
113+
2. **Optimize timeout settings:**
114+
```python
115+
app.start(
116+
client_timeout=15, # Shorter timeouts
117+
keep_alive_timeout=5 # Faster connection cleanup
118+
)
119+
```
120+
121+
3. **Use environment variables for deployment:**
122+
```bash
123+
export ROBYN_CLIENT_TIMEOUT=15
124+
export ROBYN_KEEP_ALIVE_TIMEOUT=5
125+
```
126+
127+
### Performance Tuning
128+
129+
**For high-throughput APIs:**
130+
- Lower `keep_alive_timeout` (5-15s)
131+
- Moderate `client_timeout` (15-30s)
132+
133+
**For long-running operations:**
134+
- Higher `client_timeout` (60-300s)
135+
- Standard `keep_alive_timeout` (20-30s)
136+
137+
138+
## Best Practices
139+
140+
1. **Always set explicit timeouts** in production
141+
2. **Use environment variables** for deployment-specific configuration
142+
3. **Test timeout settings** with realistic load patterns
143+
4. **Start with conservative values** and tune based on metrics
144+
145+
## Migration Guide
146+
147+
### From Previous Versions
148+
149+
If upgrading from earlier Robyn versions, the default behavior changes:
150+
151+
**Before (infinite timeout):**
152+
```python
153+
# Previously: no timeout (could cause resource exhaustion)
154+
app.start(host="0.0.0.0", port=8080)
155+
```
156+
157+
**After (sensible defaults):**
158+
```python
159+
# Now: automatic 30s client timeout, 20s keep-alive
160+
app.start(host="0.0.0.0", port=8080)
161+
# Equivalent to:
162+
app.start(
163+
host="0.0.0.0",
164+
port=8080,
165+
client_timeout=30,
166+
keep_alive_timeout=20
167+
)
168+
```
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
export const description =
2+
'配置超时设置以处理高并发场景并防止资源耗尽。'
3+
4+
# 超时配置
5+
6+
Robyn 支持全面的超时配置,以处理高并发场景并防止资源耗尽,如"打开文件过多"错误。 {{ className: 'lead' }}
7+
8+
## 配置选项
9+
10+
### 方法参数
11+
12+
直接在 `app.start()` 方法中配置超时:
13+
14+
```python
15+
from robyn import Robyn
16+
17+
app = Robyn(__file__)
18+
19+
@app.get("/")
20+
async def hello(request):
21+
return "Hello, world!"
22+
23+
# 配置超时设置
24+
app.start(
25+
host="0.0.0.0",
26+
port=8080,
27+
client_timeout=30, # 客户端连接超时(秒)
28+
keep_alive_timeout=20, # 保持连接超时(秒)
29+
)
30+
```
31+
32+
### 环境变量
33+
34+
使用环境变量覆盖配置:
35+
36+
```bash
37+
# 设置超时配置
38+
export ROBYN_CLIENT_TIMEOUT=45
39+
export ROBYN_KEEP_ALIVE_TIMEOUT=30
40+
41+
# 启动应用程序
42+
python app.py
43+
```
44+
45+
## 配置参数
46+
47+
| 参数 | 默认值 | 描述 | 环境变量 |
48+
|------|-------|------|---------|
49+
| `client_timeout` | 30 | 客户端请求处理的最大时间(秒) | `ROBYN_CLIENT_TIMEOUT` |
50+
| `keep_alive_timeout` | 20 | 保持空闲连接的时间(秒) | `ROBYN_KEEP_ALIVE_TIMEOUT` |
51+
52+
## 使用示例
53+
54+
### 基本配置
55+
56+
```python
57+
# 最小超时配置
58+
app.start(client_timeout=30)
59+
```
60+
61+
### 高流量生产设置
62+
63+
```python
64+
# 针对高流量场景优化
65+
app.start(
66+
host="0.0.0.0",
67+
port=8080,
68+
client_timeout=60, # 允许更长的处理时间
69+
keep_alive_timeout=15, # 更短的保持连接以加快周转
70+
)
71+
```
72+
73+
### 开发设置
74+
75+
```python
76+
# 开发友好设置
77+
app.start(
78+
client_timeout=300, # 调试的长超时
79+
keep_alive_timeout=60, # 测试的长保持连接
80+
)
81+
```
82+
83+
### 负载测试配置
84+
85+
```python
86+
# 针对 wrk 等工具的负载测试优化
87+
app.start(
88+
client_timeout=10, # 快速超时
89+
keep_alive_timeout=5, # 快速连接周转
90+
)
91+
```
92+
93+
## 环境变量优先级
94+
95+
环境变量优先于方法参数:
96+
97+
```python
98+
# 如果设置了 ROBYN_CLIENT_TIMEOUT=60,将使用 60,否则使用 30
99+
app.start(client_timeout=30)
100+
```
101+
102+
## 故障排除
103+
104+
### "打开文件过多"错误
105+
106+
如果遇到文件描述符耗尽:
107+
108+
1. **增加系统限制:**
109+
```bash
110+
ulimit -n 65536
111+
```
112+
113+
2. **优化超时设置:**
114+
```python
115+
app.start(
116+
client_timeout=15, # 更短的超时
117+
keep_alive_timeout=5, # 更快的连接清理
118+
)
119+
```
120+
121+
3. **在部署中使用环境变量:**
122+
```bash
123+
export ROBYN_CLIENT_TIMEOUT=15
124+
export ROBYN_KEEP_ALIVE_TIMEOUT=5
125+
```
126+
127+
### 性能调优
128+
129+
**对于高吞吐量 API:**
130+
- 较低的 `keep_alive_timeout` (5-15秒)
131+
- 中等的 `client_timeout` (15-30秒)
132+
133+
**对于长时间运行的操作:**
134+
- 较高的 `client_timeout` (60-300秒)
135+
- 标准的 `keep_alive_timeout` (20-30秒)
136+
137+
## 与其他框架的比较
138+
139+
| 框架 | 默认客户端超时 | 默认保持连接 | 配置方式 |
140+
|-----|--------------|-------------|----------|
141+
| **Robyn** | 30秒 | 20秒 | 方法参数 + 环境变量 |
142+
| Uvicorn || 20秒 | 构造函数参数 |
143+
| Express.js | 120秒 | 5秒 | 方法链式调用 |
144+
| Django/Gunicorn | 30秒 | 不适用 | 配置文件 |
145+
| Flask/Gunicorn | 30秒 | 2秒 | 命令行选项 |
146+
147+
## 最佳实践
148+
149+
1. **在生产环境中始终设置明确的超时**
150+
2. **使用环境变量进行特定部署的配置**
151+
3. **在负载下监控文件描述符使用**
152+
4. **用现实负载模式测试超时设置**
153+
5. **从保守值开始,根据指标进行调优**
154+
155+
## 迁移指南
156+
157+
### 从早期版本
158+
159+
如果从早期 Robyn 版本升级,默认行为会改变:
160+
161+
**之前(无限超时):**
162+
```python
163+
# 以前:无超时(可能导致资源耗尽)
164+
app.start(host="0.0.0.0", port=8080)
165+
```
166+
167+
**之后(合理默认值):**
168+
```python
169+
# 现在:自动 30秒 客户端超时,20秒 保持连接
170+
app.start(host="0.0.0.0", port=8080)
171+
# 等价于:
172+
app.start(
173+
host="0.0.0.0",
174+
port=8080,
175+
client_timeout=30,
176+
keep_alive_timeout=20,
177+
)
178+
```

0 commit comments

Comments
 (0)