@dangao/bun-server 1.1.2 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/api.md +602 -0
- package/docs/best-practices.md +12 -0
- package/docs/custom-decorators.md +440 -0
- package/docs/deployment.md +447 -0
- package/docs/error-handling.md +462 -0
- package/docs/extensions.md +569 -0
- package/docs/guide.md +634 -0
- package/docs/migration.md +10 -0
- package/docs/performance.md +452 -0
- package/docs/troubleshooting.md +286 -0
- package/docs/zh/api.md +168 -0
- package/docs/zh/best-practices.md +38 -0
- package/docs/zh/custom-decorators.md +466 -0
- package/docs/zh/deployment.md +445 -0
- package/docs/zh/error-handling.md +456 -0
- package/docs/zh/extensions.md +584 -0
- package/docs/zh/guide.md +361 -0
- package/docs/zh/migration.md +86 -0
- package/docs/zh/performance.md +451 -0
- package/docs/zh/troubleshooting.md +279 -0
- package/package.json +4 -3
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
# 生产部署指南
|
|
2
|
+
|
|
3
|
+
本文档介绍将 Bun Server Framework 应用部署到生产环境的最佳实践。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [前置要求](#前置要求)
|
|
8
|
+
- [环境设置](#环境设置)
|
|
9
|
+
- [配置](#配置)
|
|
10
|
+
- [进程管理](#进程管理)
|
|
11
|
+
- [反向代理](#反向代理)
|
|
12
|
+
- [监控](#监控)
|
|
13
|
+
- [安全](#安全)
|
|
14
|
+
- [扩展](#扩展)
|
|
15
|
+
|
|
16
|
+
## 前置要求
|
|
17
|
+
|
|
18
|
+
- Bun runtime(最新稳定版本)
|
|
19
|
+
- Node.js 18+(用于兼容性)
|
|
20
|
+
- 生产级数据库(PostgreSQL、MySQL 等)
|
|
21
|
+
- 反向代理(Nginx、Caddy 等)
|
|
22
|
+
|
|
23
|
+
## 环境设置
|
|
24
|
+
|
|
25
|
+
### 安装 Bun
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# 在 Linux/macOS 上
|
|
29
|
+
curl -fsSL https://bun.sh/install | bash
|
|
30
|
+
|
|
31
|
+
# 验证安装
|
|
32
|
+
bun --version
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 设置环境变量
|
|
36
|
+
|
|
37
|
+
创建 `.env.production` 文件:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
NODE_ENV=production
|
|
41
|
+
PORT=3000
|
|
42
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
|
43
|
+
JWT_SECRET=your-secret-key-here
|
|
44
|
+
LOG_LEVEL=info
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
在应用中加载环境变量:
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { ConfigModule } from "@dangao/bun-server";
|
|
51
|
+
|
|
52
|
+
ConfigModule.forRoot({
|
|
53
|
+
load: (env) => ({
|
|
54
|
+
port: Number(env.PORT) || 3000,
|
|
55
|
+
database: {
|
|
56
|
+
url: env.DATABASE_URL,
|
|
57
|
+
},
|
|
58
|
+
jwt: {
|
|
59
|
+
secret: env.JWT_SECRET,
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 配置
|
|
66
|
+
|
|
67
|
+
### 生产配置
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { Application } from "@dangao/bun-server";
|
|
71
|
+
import { ConfigModule } from "@dangao/bun-server";
|
|
72
|
+
import { LoggerModule, LogLevel } from "@dangao/bun-server";
|
|
73
|
+
|
|
74
|
+
ConfigModule.forRoot({
|
|
75
|
+
defaultConfig: {
|
|
76
|
+
app: {
|
|
77
|
+
name: "MyApp",
|
|
78
|
+
port: Number(process.env.PORT) || 3000,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
LoggerModule.forRoot({
|
|
84
|
+
logger: {
|
|
85
|
+
level: LogLevel.INFO, // 生产环境使用 INFO
|
|
86
|
+
prefix: "App",
|
|
87
|
+
},
|
|
88
|
+
enableRequestLogging: true,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const app = new Application({
|
|
92
|
+
port: Number(process.env.PORT) || 3000,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// 注册模块并启动
|
|
96
|
+
await app.listen();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### 错误处理
|
|
100
|
+
|
|
101
|
+
确保在生产环境中正确配置错误处理:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// 全局错误处理器默认已启用
|
|
105
|
+
// 如需自定义错误响应
|
|
106
|
+
app.use(async (ctx, next) => {
|
|
107
|
+
try {
|
|
108
|
+
return await next();
|
|
109
|
+
} catch (error) {
|
|
110
|
+
// 记录错误
|
|
111
|
+
console.error("Request error:", error);
|
|
112
|
+
|
|
113
|
+
// 返回适当的错误响应
|
|
114
|
+
if (error instanceof HttpException) {
|
|
115
|
+
return ctx.createResponse(
|
|
116
|
+
{ error: error.message },
|
|
117
|
+
{ status: error.statusCode },
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// 通用错误
|
|
122
|
+
return ctx.createResponse(
|
|
123
|
+
{ error: "Internal Server Error" },
|
|
124
|
+
{ status: 500 },
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 进程管理
|
|
131
|
+
|
|
132
|
+
### 使用 PM2
|
|
133
|
+
|
|
134
|
+
安装 PM2:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npm install -g pm2
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
创建 `ecosystem.config.js`:
|
|
141
|
+
|
|
142
|
+
```javascript
|
|
143
|
+
module.exports = {
|
|
144
|
+
apps: [{
|
|
145
|
+
name: "bun-server-app",
|
|
146
|
+
script: "bun",
|
|
147
|
+
args: "run src/index.ts",
|
|
148
|
+
instances: "max", // 使用所有 CPU 核心
|
|
149
|
+
exec_mode: "cluster",
|
|
150
|
+
env: {
|
|
151
|
+
NODE_ENV: "production",
|
|
152
|
+
PORT: 3000,
|
|
153
|
+
},
|
|
154
|
+
error_file: "./logs/error.log",
|
|
155
|
+
out_file: "./logs/out.log",
|
|
156
|
+
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
|
|
157
|
+
merge_logs: true,
|
|
158
|
+
}],
|
|
159
|
+
};
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
使用 PM2 启动:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
pm2 start ecosystem.config.js
|
|
166
|
+
pm2 save
|
|
167
|
+
pm2 startup # 启用系统重启后自动启动
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 使用 systemd
|
|
171
|
+
|
|
172
|
+
创建 `/etc/systemd/system/bun-server.service`:
|
|
173
|
+
|
|
174
|
+
```ini
|
|
175
|
+
[Unit]
|
|
176
|
+
Description=Bun Server Application
|
|
177
|
+
After=network.target
|
|
178
|
+
|
|
179
|
+
[Service]
|
|
180
|
+
Type=simple
|
|
181
|
+
User=www-data
|
|
182
|
+
WorkingDirectory=/var/www/bun-server
|
|
183
|
+
ExecStart=/usr/local/bin/bun run src/index.ts
|
|
184
|
+
Restart=always
|
|
185
|
+
RestartSec=10
|
|
186
|
+
Environment=NODE_ENV=production
|
|
187
|
+
Environment=PORT=3000
|
|
188
|
+
|
|
189
|
+
[Install]
|
|
190
|
+
WantedBy=multi-user.target
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
启用并启动:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
sudo systemctl enable bun-server
|
|
197
|
+
sudo systemctl start bun-server
|
|
198
|
+
sudo systemctl status bun-server
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 反向代理
|
|
202
|
+
|
|
203
|
+
### Nginx 配置
|
|
204
|
+
|
|
205
|
+
```nginx
|
|
206
|
+
upstream bun_server {
|
|
207
|
+
server localhost:3000;
|
|
208
|
+
keepalive 64;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
server {
|
|
212
|
+
listen 80;
|
|
213
|
+
server_name example.com;
|
|
214
|
+
|
|
215
|
+
# 将 HTTP 重定向到 HTTPS
|
|
216
|
+
return 301 https://$server_name$request_uri;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
server {
|
|
220
|
+
listen 443 ssl http2;
|
|
221
|
+
server_name example.com;
|
|
222
|
+
|
|
223
|
+
ssl_certificate /path/to/cert.pem;
|
|
224
|
+
ssl_certificate_key /path/to/key.pem;
|
|
225
|
+
|
|
226
|
+
# 安全头
|
|
227
|
+
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
228
|
+
add_header X-Content-Type-Options "nosniff" always;
|
|
229
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
|
230
|
+
|
|
231
|
+
# Gzip 压缩
|
|
232
|
+
gzip on;
|
|
233
|
+
gzip_vary on;
|
|
234
|
+
gzip_min_length 1024;
|
|
235
|
+
gzip_types text/plain text/css application/json application/javascript;
|
|
236
|
+
|
|
237
|
+
location / {
|
|
238
|
+
proxy_pass http://bun_server;
|
|
239
|
+
proxy_http_version 1.1;
|
|
240
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
241
|
+
proxy_set_header Connection 'upgrade';
|
|
242
|
+
proxy_set_header Host $host;
|
|
243
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
244
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
245
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
|
246
|
+
proxy_cache_bypass $http_upgrade;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Caddy 配置
|
|
252
|
+
|
|
253
|
+
创建 `Caddyfile`:
|
|
254
|
+
|
|
255
|
+
```
|
|
256
|
+
example.com {
|
|
257
|
+
reverse_proxy localhost:3000 {
|
|
258
|
+
header_up X-Real-IP {remote_host}
|
|
259
|
+
header_up X-Forwarded-For {remote_host}
|
|
260
|
+
header_up X-Forwarded-Proto {scheme}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## 监控
|
|
266
|
+
|
|
267
|
+
### 健康检查
|
|
268
|
+
|
|
269
|
+
使用内置的 HealthModule:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
import { HealthModule } from "@dangao/bun-server";
|
|
273
|
+
|
|
274
|
+
HealthModule.forRoot({
|
|
275
|
+
indicators: [
|
|
276
|
+
{
|
|
277
|
+
name: "database",
|
|
278
|
+
check: async () => {
|
|
279
|
+
// 检查数据库连接
|
|
280
|
+
await db.query("SELECT 1");
|
|
281
|
+
return { status: "up" };
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// 健康检查端点:
|
|
288
|
+
// GET /health - 整体健康状态
|
|
289
|
+
// GET /ready - 就绪检查
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### 日志
|
|
293
|
+
|
|
294
|
+
配置结构化日志:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
LoggerModule.forRoot({
|
|
298
|
+
logger: {
|
|
299
|
+
level: LogLevel.INFO,
|
|
300
|
+
format: "json", // 生产环境使用 JSON
|
|
301
|
+
},
|
|
302
|
+
enableRequestLogging: true,
|
|
303
|
+
});
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### 指标
|
|
307
|
+
|
|
308
|
+
使用 MetricsModule 获取应用指标:
|
|
309
|
+
|
|
310
|
+
```typescript
|
|
311
|
+
import { MetricsModule } from "@dangao/bun-server";
|
|
312
|
+
|
|
313
|
+
MetricsModule.forRoot({
|
|
314
|
+
enableDefaultMetrics: true,
|
|
315
|
+
enableHttpMetrics: true,
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
// 指标端点:GET /metrics
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
## 安全
|
|
322
|
+
|
|
323
|
+
### HTTPS
|
|
324
|
+
|
|
325
|
+
在生产环境中始终使用 HTTPS。配置 SSL/TLS 证书(Let's Encrypt 等)。
|
|
326
|
+
|
|
327
|
+
### 安全头
|
|
328
|
+
|
|
329
|
+
添加安全中间件:
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
app.use(async (ctx, next) => {
|
|
333
|
+
const response = await next();
|
|
334
|
+
response.headers.set("X-Frame-Options", "SAMEORIGIN");
|
|
335
|
+
response.headers.set("X-Content-Type-Options", "nosniff");
|
|
336
|
+
response.headers.set("X-XSS-Protection", "1; mode=block");
|
|
337
|
+
response.headers.set("Strict-Transport-Security", "max-age=31536000");
|
|
338
|
+
return response;
|
|
339
|
+
});
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### 限流
|
|
343
|
+
|
|
344
|
+
启用限流:
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
import { createRateLimitMiddleware } from "@dangao/bun-server";
|
|
348
|
+
|
|
349
|
+
app.use(createRateLimitMiddleware({
|
|
350
|
+
windowMs: 15 * 60 * 1000, // 15 分钟
|
|
351
|
+
max: 100, // 每个 IP 在 windowMs 内限制 100 个请求
|
|
352
|
+
}));
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 输入验证
|
|
356
|
+
|
|
357
|
+
始终验证输入:
|
|
358
|
+
|
|
359
|
+
```typescript
|
|
360
|
+
import { Validate, IsString, IsEmail } from '@dangao/bun-server';
|
|
361
|
+
|
|
362
|
+
class CreateUserDto {
|
|
363
|
+
@IsString()
|
|
364
|
+
public name!: string;
|
|
365
|
+
|
|
366
|
+
@IsEmail()
|
|
367
|
+
public email!: string;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
@POST('/users')
|
|
371
|
+
public createUser(@Body() @Validate() user: CreateUserDto) {
|
|
372
|
+
// 用户已通过验证
|
|
373
|
+
}
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## 扩展
|
|
377
|
+
|
|
378
|
+
### 水平扩展
|
|
379
|
+
|
|
380
|
+
在负载均衡器后运行多个实例:
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# 启动多个实例
|
|
384
|
+
PORT=3000 bun run src/index.ts &
|
|
385
|
+
PORT=3001 bun run src/index.ts &
|
|
386
|
+
PORT=3002 bun run src/index.ts &
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
配置负载均衡器(Nginx、HAProxy 等)以分发流量。
|
|
390
|
+
|
|
391
|
+
### 数据库连接池
|
|
392
|
+
|
|
393
|
+
配置连接池:
|
|
394
|
+
|
|
395
|
+
```typescript
|
|
396
|
+
DatabaseModule.forRoot({
|
|
397
|
+
database: {
|
|
398
|
+
type: "postgres",
|
|
399
|
+
config: {
|
|
400
|
+
connectionString: process.env.DATABASE_URL,
|
|
401
|
+
max: 20, // 最大池大小
|
|
402
|
+
min: 5, // 最小池大小
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 缓存
|
|
409
|
+
|
|
410
|
+
使用 CacheModule 缓存频繁访问的数据:
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
CacheModule.forRoot({
|
|
414
|
+
store: new RedisCacheStore(redisClient),
|
|
415
|
+
defaultTtl: 3600000, // 1 小时
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
### 会话存储
|
|
420
|
+
|
|
421
|
+
使用 Redis 进行分布式会话存储:
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
SessionModule.forRoot({
|
|
425
|
+
store: new RedisSessionStore(redisClient),
|
|
426
|
+
maxAge: 86400000, // 24 小时
|
|
427
|
+
});
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
## 检查清单
|
|
431
|
+
|
|
432
|
+
部署到生产环境前:
|
|
433
|
+
|
|
434
|
+
- [ ] 环境变量已配置
|
|
435
|
+
- [ ] HTTPS 已启用
|
|
436
|
+
- [ ] 错误处理已配置
|
|
437
|
+
- [ ] 日志已配置
|
|
438
|
+
- [ ] 健康检查已启用
|
|
439
|
+
- [ ] 限流已启用
|
|
440
|
+
- [ ] 安全头已设置
|
|
441
|
+
- [ ] 数据库连接池已配置
|
|
442
|
+
- [ ] 进程管理器已配置(PM2/systemd)
|
|
443
|
+
- [ ] 反向代理已配置
|
|
444
|
+
- [ ] 监控已设置
|
|
445
|
+
- [ ] 备份策略已就位
|