dynapm 1.0.12 → 1.0.14

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/CHANGELOG.md CHANGED
@@ -5,6 +5,47 @@
5
5
  格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
6
6
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
7
7
 
8
+ ## [1.0.14] - 2026-03-20
9
+
10
+ ### 🔴 Bug 修复
11
+ - **按需启动 POST 请求体丢失(严重)**: uWS 的 onData 回调中 ArrayBuffer 是借用语义,`Buffer.from(ab)` 底层数据被后续回调覆盖。改用 `Buffer.alloc + copy` 确保数据复制
12
+ - **并发按需启动返回 502**: 多个请求同时到达离线服务时,只有第一个触发启动,其他请求等待启动完成后再代理
13
+ - **transfer-encoding 头冲突**: forwardProxyRequest 中过滤 transfer-encoding 头,避免与 content-length 冲突导致后端 400
14
+ - **后端崩溃自动恢复**: 检测到后端不可达(ECONNREFUSED)时,自动将非 proxyOnly 服务状态重置为 offline
15
+ - **端口路由并发启动**: handlePortBindingRequest 补全 starting/stopping 状态处理,与 hostname 路由保持一致
16
+
17
+ ### 🔒 安全加固
18
+ - 请求体大小限制 10MB,防止 DoS 攻击
19
+ - WebSocket 消息队列限制 1000 条,防止内存泄漏
20
+ - CRLF 注入防护:请求头值中的 `\r\n` 被清理
21
+ - 端口路由 WebSocket close handler 补充后端连接清理
22
+
23
+ ### 🚀 性能优化
24
+ - **去除 undici,恢复原生 http 模块**: 吞吐量从 4,523 提升至 **5,942 req/s(+31%)**,延迟从 10.6ms 降至 **10.3ms**
25
+ - 预编译 CRLF 正则,避免热路径重复创建
26
+ - Set 替代内联条件判断,优化请求头跳过逻辑
27
+
28
+ ### 🧪 测试(81 个用例全部通过)
29
+ - test-proxy-comprehensive.ts: 23 个综合代理测试
30
+ - test-edge-cases.ts: 15 个极端场景测试
31
+ - test-gateway-robustness.ts: 13 个健壮性测试
32
+ - test-admin-api-lifecycle.ts: 12 个管理 API 生命周期测试
33
+ - test-port-route-start.ts: 9 个端口路由按需启动测试
34
+ - test-security-stability.ts: 9 个安全与稳定性深度测试
35
+
36
+ ---
37
+
38
+ ## [1.0.13] - 2026-02-10
39
+
40
+ ### 🚀 性能优化
41
+ - 使用 undici 替代原生 http 模块(已在 v1.0.14 回退,原生 http 性能更优)
42
+
43
+ ### 🔧 改进
44
+ - 清理 RouteMapping 中的冗余字段
45
+ - 代码更简洁,维护性更好
46
+
47
+ ---
48
+
8
49
  ## [1.0.12] - 2026-02-10
9
50
 
10
51
  ### ✨ 新增
package/CLAUDE.md CHANGED
@@ -1,21 +1,20 @@
1
1
  # DynaPM - Claude Code 项目配置
2
2
 
3
- DynaPM 是一个智能网关,通过按需启动和闲置自动停止的方式,帮助用户在资源受限的服务器上管理数百个低频访问的服务。
3
+ DynaPM 是一个智能网关(类似nginx)/进程管理工具(类似pm2),通过按需启动(请求到达时通过查找配置判断请求属于哪个程序,然后网关转发请求,当程序还未启动会执行启动命令等待就绪后再实际转发)和闲置自动停止的方式,帮助用户在资源受限的服务器上运行成千上万个低频访问+少量高频访问的服务。
4
4
 
5
5
  **核心特性:**
6
- - ⚡ 极速冷启动(开销仅 25ms)
7
- - 🚀 流式代理(1-2ms 延迟)
6
+ - ⚡ 极速冷启动
7
+ - 🚀 双向流式转发代理实现极低的请求延迟:将请求体流式给代理服务,将代理服务的响应流式给请求者 所以不需要缓冲请求或者响应,唯一的需要缓冲的时机就是请求到达网关,但是需要被网关唤起的程序还没有启动成功的时候
8
8
  - 🌐 支持 SSE 和 WebSocket
9
- - 🎛️ 通用服务管理(可替代PM2、Docker、systemd 等)
10
- - 🔄 闲置自动回收
9
+ - 🎛️ 基于bash的通用服务管理(可用于管理PM2、Docker、systemd 等任意服务)
10
+ - 🔄 闲置自动回收资源
11
11
 
12
12
  ## 技术栈
13
13
 
14
14
  - **运行时**: Node.js 22+
15
- - **Web 框架**: uWebSockets.js(性能比 Fastify 快 10 倍以上)
16
- - **日志**: Pino(异步结构化日志)
15
+ - **Web 框架**: uWebSockets.js(最佳性能)
16
+ - **日志**: Pino
17
17
  - **配置**: c12(支持 TypeScript)
18
- - **构建**: rslib
19
18
  - **包管理**: pnpm
20
19
  - **测试**: tsx + 自定义测试套件
21
20
 
@@ -37,8 +36,6 @@ DynaPM/
37
36
  │ ├── test-all.ts # 完整测试套件(12个测试)
38
37
  │ ├── server-*.ts # 测试服务器
39
38
  │ └── benchmark.js # 性能测试
40
- ├── docs/
41
- │ └── NPM_OIDC_SETUP.md # npm OIDC 发布配置指南
42
39
  ├── .github/workflows/
43
40
  │ └── release.yml # 自动发布到 npm
44
41
  ├── CHANGELOG.md # 版本更新日志
@@ -49,12 +46,7 @@ DynaPM/
49
46
 
50
47
  ## 开发指南
51
48
 
52
- ### 快速开始
53
-
54
49
  ```bash
55
- # 安装依赖
56
- pnpm install
57
-
58
50
  # 运行测试
59
51
  pnpm test
60
52
 
@@ -67,4 +59,4 @@ pnpm benchmark
67
59
 
68
60
  ### 发布新版本
69
61
 
70
- 流程 : CHANGELOG → commit npm version (git tag) → push
62
+ 流程 : CHANGELOG → commit →更新 npm version (git add tag) →git push (github actions 会通过 oicd 发包 npm )
package/README.md CHANGED
@@ -4,9 +4,7 @@
4
4
 
5
5
  > **Dynamic Process Manager** - A lightweight, universal service management system with serverless-like features.
6
6
 
7
- [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm)
8
- ![Tests](https://img.shields.io/badge/tests-12%2F12 passing-green)
9
- ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
7
+ [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-81%2F81%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
10
8
 
11
9
  DynaPM is a **lightweight alternative** to complex container orchestration platforms (like Knative, Sablier) for private deployments. It helps you manage hundreds of low-frequency services on resource-constrained servers by starting them on-demand and stopping them when idle.
12
10
 
@@ -59,7 +57,7 @@ You have many side projects or internal tools that:
59
57
 
60
58
  - **DynaPM overhead**: Only **25ms** (startup command: 8ms + port wait: 17ms)
61
59
  - **Instant retry**: Zero-delay polling, forward immediately when port is ready
62
- - **Total cold start**: ~500ms (including service boot time, e.g., ~475ms for Node.js apps)
60
+ - **Total cold start**: ~185ms (including service boot time, e.g., ~160ms for Node.js apps)
63
61
 
64
62
  ### 🚀 **Stream Proxying**
65
63
 
@@ -149,9 +147,9 @@ Configure ANY service using bash commands - no limits:
149
147
  ```
150
148
  Test Environment: Node.js HTTP Server (autocannon benchmark)
151
149
 
152
- ✅ Cold start: ~48ms (DynaPM: 25ms + service boot: 23ms)
153
- ✅ Stream proxy: Avg 9.5ms (range: 8-14ms)
154
- ✅ Throughput: 8,383 req/s (multi-service, 60 concurrent)
150
+ ✅ Cold start: ~185ms (DynaPM: 25ms + service boot: 160ms)
151
+ ✅ Stream proxy: Avg 10.3ms (range: 9-12ms)
152
+ ✅ Throughput: 5,942 req/s (multi-service, 150 concurrent)
155
153
  ✅ Load test: Low latency even under high concurrency
156
154
  ✅ Memory overhead: ~50MB (Node.js runtime)
157
155
  ✅ Bundle size: 21.7KB (minified)
@@ -183,6 +181,13 @@ const config: DynaPMConfig = {
183
181
  port: 3000,
184
182
  host: '127.0.0.1',
185
183
 
184
+ // Logging configuration (optional, disable for better performance in production)
185
+ logging: {
186
+ enableRequestLog: false, // Enable request/response logging (high frequency, affects performance)
187
+ enableWebSocketLog: false, // Enable WebSocket lifecycle logging
188
+ // Error logging is always enabled
189
+ },
190
+
186
191
  services: {
187
192
  'app.example.com': {
188
193
  name: 'my-app',
@@ -240,7 +245,7 @@ pnpm test
240
245
 
241
246
  ### Test Coverage
242
247
 
243
- The automated tests validate 12 core functionalities:
248
+ The automated tests validate 81 test cases across 6 test suites:
244
249
 
245
250
  1. ✅ **On-demand start** - Services auto-start when offline
246
251
  2. ✅ **Hot start** - Direct proxy when service is running
@@ -254,6 +259,9 @@ The automated tests validate 12 core functionalities:
254
259
  10. ✅ **SSE streaming** - Server-Sent Events proxy support
255
260
  11. ✅ **WebSocket** - WebSocket bidirectional communication support
256
261
  12. ✅ **Long connections** - Active connections prevent premature shutdown
262
+ 13. ✅ **Concurrent startup** - Multiple requests to offline service
263
+ 14. ✅ **Security hardening** - Body size limits, CRLF injection protection
264
+ 15. ✅ **Port routing** - Direct port-based proxy and on-demand start
257
265
 
258
266
  ### Test Output Example
259
267
 
@@ -421,8 +429,8 @@ Test: Total time from offline to first accessible request
421
429
 
422
430
  Results:
423
431
  ├─ DynaPM overhead: 25ms (startup command: 8ms + TCP port wait: 17ms)
424
- ├─ Service boot: 17ms (Node.js application)
425
- └─ Total cold start: 42ms
432
+ ├─ Service boot: 160ms (Node.js application)
433
+ └─ Total cold start: 185ms
426
434
  ```
427
435
 
428
436
  ### Stream Proxy Performance
@@ -431,30 +439,23 @@ Results:
431
439
  Test: Single request latency when service is running
432
440
 
433
441
  Results:
434
- ├─ Average latency: 9.3ms
435
- ├─ Min latency: 8ms
442
+ ├─ Average latency: 10.3ms
443
+ ├─ Min latency: 9ms
436
444
  ├─ Max latency: 12ms
437
- └─ Latency range: 8-12ms
445
+ └─ Latency range: 9-12ms
438
446
  ```
439
447
 
440
448
  ### Throughput Performance
441
449
 
442
450
  ```
443
- Test: Multi-service benchmark (3 services × 20 concurrent, 5 seconds)
451
+ Test: Multi-service benchmark (3 services × 50 concurrent, 5 seconds)
444
452
 
445
453
  Results:
446
- ├─ Total requests: 42,000 requests
447
- ├─ Average throughput: 8,383 req/s
448
- ├─ Per-service: 2,794 req/s
454
+ ├─ Total requests: 29,710 requests
455
+ ├─ Average throughput: 5,942 req/s
456
+ ├─ Per-service: ~1,980 req/s
449
457
  ├─ Errors: 0
450
458
  └─ Test duration: 5 seconds
451
-
452
- Test: Single service benchmark (50 concurrent, 5 seconds)
453
-
454
- Results:
455
- ├─ Requests/sec: 4,225+ req/s
456
- ├─ Average latency: ~23ms
457
- └─ Total requests: 21k requests
458
459
  ```
459
460
 
460
461
  ### Resource Usage
package/README_zh.md CHANGED
@@ -4,9 +4,7 @@
4
4
 
5
5
  > **动态进程管理器** - 具有类 serverless 特性的轻量级通用服务管理系统
6
6
 
7
- [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm)
8
- ![Tests](https://img.shields.io/badge/tests-12%2F12 passing-green)
9
- ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
7
+ [![npm version](https://badge.fury.io/js/dynapm.svg)](https://www.npmjs.com/package/dynapm) ![Tests](https://img.shields.io/badge/tests-81%2F81%20passing-green) ![Performance](https://img.shields.io/badge/overhead-25ms-brightgreen)
10
8
 
11
9
  DynaPM 是**复杂容器编排平台(如 Knative、Sablier)的轻量级替代方案**,专为私有化部署设计。它通过按需启动和闲置自动停止的方式,帮助你在资源受限的服务器上管理数百个低频访问的服务。
12
10
 
@@ -59,7 +57,7 @@ DynaPM 是**复杂容器编排平台(如 Knative、Sablier)的轻量级替
59
57
 
60
58
  - **DynaPM 开销**:仅 **25ms**(启动命令 8ms + 端口等待 17ms)
61
59
  - **失败立即重试**:无延迟轮询,端口可用即刻转发
62
- - **总冷启动**:~500ms(包括服务本身启动时间,如 Node.js 应用 ~475ms
60
+ - **总冷启动**:~185ms(包括服务本身启动时间,如 Node.js 应用 ~160ms
63
61
 
64
62
  ### 🚀 **流式代理**
65
63
 
@@ -148,9 +146,9 @@ DynaPM 原生支持现代实时通信协议:
148
146
  ```
149
147
  测试环境:Node.js HTTP 服务器 (autocannon 压测)
150
148
 
151
- ✅ 冷启动时间: ~48ms (DynaPM: 25ms + 服务启动: 23ms)
152
- ✅ 流式代理延迟: 平均 9.5ms (范围: 8-14ms)
153
- ✅ 吞吐量: 8,383 req/s (多服务, 60 并发)
149
+ ✅ 冷启动时间: ~185ms (DynaPM: 25ms + 服务启动: 160ms)
150
+ ✅ 流式代理延迟: 平均 10.3ms (范围: 9-12ms)
151
+ ✅ 吞吐量: 5,942 req/s (多服务, 150 并发)
154
152
  ✅ 压测延迟: 高并发下保持低延迟
155
153
  ✅ 内存开销: ~50MB (Node.js 运行时)
156
154
  ✅ 代码体积: 21.7KB (压缩后)
@@ -182,6 +180,13 @@ const config: DynaPMConfig = {
182
180
  port: 3000,
183
181
  host: '127.0.0.1',
184
182
 
183
+ // 日志配置(可选,生产环境建议关闭以提升性能)
184
+ logging: {
185
+ enableRequestLog: false, // 是否启用请求日志(高频,影响性能)
186
+ enableWebSocketLog: false, // 是否启用 WebSocket 生命周期日志
187
+ // 错误日志始终启用,不受此开关控制
188
+ },
189
+
185
190
  services: {
186
191
  'app.example.com': {
187
192
  name: 'my-app',
@@ -239,7 +244,7 @@ pnpm test
239
244
 
240
245
  ### 测试覆盖场景
241
246
 
242
- 自动化测试会验证以下 12 个核心功能:
247
+ 自动化测试会验证以下 81 个测试用例(6 个测试套件):
243
248
 
244
249
  1. ✅ **按需启动** - 服务离线时自动启动
245
250
  2. ✅ **热启动** - 服务运行时直接代理,无需重新启动
@@ -253,6 +258,9 @@ pnpm test
253
258
  10. ✅ **SSE 流式传输** - Server-Sent Events 代理支持
254
259
  11. ✅ **WebSocket** - WebSocket 双向通信支持
255
260
  12. ✅ **长连接代理** - 活跃连接阻止服务被提前关闭
261
+ 13. ✅ **并发启动** - 多个请求同时到达离线服务
262
+ 14. ✅ **安全加固** - 请求体大小限制、CRLF 注入防护
263
+ 15. ✅ **端口路由** - 端口直连代理和按需启动
256
264
 
257
265
  ### 测试输出示例
258
266
 
@@ -419,8 +427,8 @@ npm install -g autocannon
419
427
 
420
428
  结果:
421
429
  ├─ DynaPM 开销: 25ms (启动命令 8ms + TCP 端口等待 17ms)
422
- ├─ 服务启动时间: 17ms (Node.js 应用)
423
- └─ 总冷启动时间: 42ms
430
+ ├─ 服务启动时间: 160ms (Node.js 应用)
431
+ └─ 总冷启动时间: 185ms
424
432
  ```
425
433
 
426
434
  ### 流式代理性能
@@ -429,22 +437,22 @@ npm install -g autocannon
429
437
  测试:服务运行时的单次请求延迟
430
438
 
431
439
  结果:
432
- ├─ 平均延迟: 9.3ms
433
- ├─ 最小延迟: 8ms
440
+ ├─ 平均延迟: 10.3ms
441
+ ├─ 最小延迟: 9ms
434
442
  ├─ 最大延迟: 12ms
435
- └─ 延迟范围: 8-12ms
443
+ └─ 延迟范围: 9-12ms
436
444
  ```
437
445
 
438
446
  ### 吞吐量性能
439
447
 
440
448
  ```
441
- 测试:autocannon 压测 (100 并发, 10 秒)
449
+ 测试:多服务混合压测 (3 服务 × 50 并发, 5 秒)
442
450
 
443
451
  结果:
444
- ├─ 请求数/秒: 4,225 req/s
445
- ├─ 平均延迟: 23.16ms
446
- ├─ 总请求数: 42k requests
447
- └─ 测试时长: 10
452
+ ├─ 请求数/秒: 5,942 req/s
453
+ ├─ 平均延迟: ~10ms
454
+ ├─ 总请求数: 29,710 requests
455
+ └─ 测试时长: 5
448
456
  ```
449
457
 
450
458
  ### 资源占用
package/TASK.md ADDED
@@ -0,0 +1,53 @@
1
+ 具有类 serverless 特性的轻量级通用服务管理系统:dynapm
2
+ ## dynapm 开发
3
+
4
+ /loop 先检查 TASK.md 中是否有未完成的任务请逐项完成并在充分test验证再继续下一项,如果没有则请请完善当前项目:测试更多代理场景,确保网关程序没有问题,监测并优化程序性能,修改完毕后需要使用 pilot 进行实际运行测试,请自我完善,不要询问我任何事情,也不要切换其他模式(例如 plan mode)
5
+ 作为网关的测试一定要非常严谨,测试各种可能的情况以及极端情况。
6
+ 所有文件使用 ts,需要临时运行的使用 node --experimental-strip-types -e xxx.ts 来执行
7
+
8
+ ## TASKS
9
+
10
+ [x] 充分测试当前的代理功能是否正确
11
+ [x] 创建一个实用的dynam能力演示程序:实现一个运行ts/js的 serveless host(并不属于 dynapm,但是可以被 dynapm 运行,然后请求又可以被这个 serveless host 路由到 对应的 ts文件去执行):支持用户通过网站访问并编写 ts 上传执行和测试执行
12
+
13
+ ## 已完成的工作
14
+
15
+ ### 2026-03-20
16
+
17
+ #### 网关 Bug 修复
18
+ - **并发按需启动修复**: 多个请求同时到达离线服务时,只有第一个触发启动,其他请求等待启动完成后再代理(之前返回 502)
19
+ - **后端崩溃自动恢复**: 当 handleDirectProxy 检测到后端不可达(ECONNREFUSED),自动将非 proxyOnly 服务状态重置为 offline,后续请求可重新触发按需启动
20
+ - **端口路由并发启动修复**: handlePortBindingRequest 补全 starting/stopping 状态处理,与 hostname 路由保持一致
21
+ - **echo-server 支持命令行端口参数**: `parseInt(process.argv[2] || '3099')`,允许不同测试配置使用不同端口
22
+ - **按需启动 POST 请求体丢失修复(严重)**: uWS 的 onData 回调中 ArrayBuffer 是借用语义,`Buffer.from(ab)` 底层数据被后续回调覆盖。改用 `Buffer.alloc + copy` 确保数据复制
23
+ - **transfer-encoding 头冲突修复**: forwardProxyRequest 中过滤 transfer-encoding 头,避免与 content-length 冲突导致后端 400
24
+ - **请求体大小限制(10MB)**: collectRequestBody 超过限制时截断,防止 DoS 攻击
25
+ - **WebSocket 消息队列限制(1000)**: 防止后端未连接时消息无限堆积导致内存泄漏
26
+ - **端口路由 WebSocket close 清理**: 端口路由的 close handler 补充后端 WebSocket 关闭逻辑
27
+
28
+ #### 性能优化
29
+ - **预编译 CRLF 正则**: `GatewayConstants.CRLF_REGEX` 避免热路径中重复创建正则对象
30
+ - **Set 替代内联条件**: `GatewayConstants.SKIP_REQUEST_HEADERS` 使用 Set.has() 替代重复 toLowerCase + 条件判断
31
+
32
+ #### 测试覆盖(81 个测试全部通过)
33
+ - **test-proxy-comprehensive.ts**: 23 个综合代理测试
34
+ - **test-edge-cases.ts**: 15 个极端场景测试
35
+ - **test-gateway-robustness.ts**: 13 个健壮性测试
36
+ - **test-port-route-start.ts**: 9 个端口路由按需启动测试
37
+ - **test-admin-api-lifecycle.ts**: 12 个管理 API 生命周期测试
38
+ - **test-security-stability.ts**: 9 个安全与稳定性深度测试
39
+ - 端口路由并发按需启动(10个同时请求)
40
+ - 端口路由多种 HTTP 方法(GET/POST/PUT/DELETE/OPTIONS/PATCH)
41
+ - 端口路由查询参数转发(含中文编码)
42
+ - 端口路由大请求体转发(100KB)
43
+ - 端口路由流式响应(20 chunks)
44
+ - 端口路由状态码透传(200/201/400/404/500)
45
+ - 端口路由 CRLF 注入防护
46
+ - 端口路由后端崩溃恢复
47
+ - 端口路由闲置后重新按需启动
48
+
49
+ #### Serverless Host 演示
50
+ - test/services/serverless-host.ts: 轻量级 TypeScript Serverless 运行时
51
+ - Web 管理界面编写/上传/执行/删除函数
52
+ - 使用 Node --experimental-strip-types 直接加载 TS 函数
53
+ - 已添加到 dynapm.config.ts 作为 serverless-host 服务
@@ -30,6 +30,15 @@ export interface ServiceCommands {
30
30
  /** 环境变量(可选) */
31
31
  env?: Record<string, string>;
32
32
  }
33
+ /** 路由配置 */
34
+ export interface RouteConfig {
35
+ /** 路由类型 */
36
+ type: 'host' | 'port';
37
+ /** 路由值:网关端的 hostname 或端口号 */
38
+ value: string | number;
39
+ /** 目标后端地址:转发到的实际服务地址 */
40
+ target: string;
41
+ }
33
42
  /** 服务配置 */
34
43
  export interface ServiceConfig {
35
44
  /** 服务标识 */
@@ -46,16 +55,52 @@ export interface ServiceConfig {
46
55
  healthCheck?: HealthCheckConfig;
47
56
  /** 纯代理模式:只做反向代理,不启动/停止服务 */
48
57
  proxyOnly?: boolean;
58
+ /** Hostname 映射(可选):配置后可通过此 hostname 访问 */
59
+ host?: string;
60
+ /** 专属端口(可选):配置后网关会监听此端口 */
61
+ port?: number;
62
+ /** 路由配置(可选):配置多个访问地址 */
63
+ routes?: RouteConfig[];
49
64
  /** 运行时状态(内部使用) */
50
65
  _state?: ServiceState;
51
66
  }
52
67
  /** 服务运行状态 */
53
68
  export interface ServiceState {
54
- status: 'offline' | 'starting' | 'online';
69
+ status: 'offline' | 'starting' | 'online' | 'stopping';
55
70
  lastAccessTime: number;
56
71
  /** 当前活动连接数(HTTP/SSE/WebSocket) */
57
72
  activeConnections: number;
58
73
  pid?: number;
74
+ /** 服务启动时间戳 */
75
+ startTime?: number;
76
+ /** 累计启动次数 */
77
+ startCount: number;
78
+ /** 累计运行时长(毫秒) */
79
+ totalUptime: number;
80
+ }
81
+ /** 管理 API 配置 */
82
+ export interface AdminApiConfig {
83
+ /** 是否启用管理 API */
84
+ enabled?: boolean;
85
+ /** 管理 API 端口(独立监听) */
86
+ port?: number;
87
+ /** 管理 API hostname(可选,使用主端口时需配置) */
88
+ host?: string;
89
+ /** API 认证令牌(可选) */
90
+ authToken?: string;
91
+ /** 允许访问的 IP 白名单 */
92
+ allowedIps?: string[];
93
+ }
94
+ /** 日志配置 */
95
+ export interface LoggingConfig {
96
+ /** 是否启用请求日志(每个请求响应记录) */
97
+ enableRequestLog?: boolean;
98
+ /** 是否启用 WebSocket 生命周期日志 */
99
+ enableWebSocketLog?: boolean;
100
+ /** 是否启用错误日志(始终启用,不受此开关控制) */
101
+ enableErrorLog?: boolean;
102
+ /** 是否启用性能分析日志(用于性能优化调试) */
103
+ enablePerformanceLog?: boolean;
59
104
  }
60
105
  /** DynaPM全局配置 */
61
106
  export interface DynaPMConfig {
@@ -65,4 +110,8 @@ export interface DynaPMConfig {
65
110
  host?: string;
66
111
  /** 服务映射:hostname -> 服务配置 */
67
112
  services: Record<string, ServiceConfig>;
113
+ /** 管理 API 配置 */
114
+ adminApi?: AdminApiConfig;
115
+ /** 日志配置 */
116
+ logging?: LoggingConfig;
68
117
  }
@@ -0,0 +1,76 @@
1
+ import type { ServiceConfig } from '../config/types.js';
2
+ import type { HttpResponse, HttpRequest } from 'uWebSockets.js';
3
+ import type { Logger } from 'pino';
4
+ import type { ServiceManager } from './service-manager.js';
5
+ /**
6
+ * 路由映射信息
7
+ */
8
+ interface RouteMapping {
9
+ /** 服务配置 */
10
+ service: ServiceConfig;
11
+ /** 目标后端地址 */
12
+ target: string;
13
+ }
14
+ /**
15
+ * 管理处理器
16
+ * 处理所有管理 API 请求
17
+ */
18
+ export declare class AdminApiHandler {
19
+ private config;
20
+ private logger;
21
+ private hostnameRoutes;
22
+ private portRoutes;
23
+ private serviceManager;
24
+ constructor(config: DynaPMConfig, logger: Logger, hostnameRoutes: Map<string, RouteMapping>, portRoutes: Map<number, RouteMapping>, serviceManager: ServiceManager);
25
+ /**
26
+ * 检查客户端 IP 是否在允许列表中
27
+ */
28
+ private isIpAllowed;
29
+ /**
30
+ * 检查认证令牌是否有效
31
+ */
32
+ private isAuthenticated;
33
+ /**
34
+ * 获取服务运行时长
35
+ */
36
+ private getServiceUptime;
37
+ /**
38
+ * 在所有路由表中查找服务
39
+ */
40
+ private findServiceMapping;
41
+ /**
42
+ * 处理管理 API 请求
43
+ */
44
+ handleAdminApi(res: HttpResponse, req: HttpRequest): void;
45
+ /**
46
+ * 获取服务列表
47
+ */
48
+ private getServicesList;
49
+ /**
50
+ * 获取服务详情
51
+ */
52
+ private getServiceDetail;
53
+ /**
54
+ * 停止服务
55
+ */
56
+ stopService(res: HttpResponse, serviceName: string): Promise<void>;
57
+ /**
58
+ * 启动服务
59
+ */
60
+ startService(res: HttpResponse, serviceName: string): Promise<void>;
61
+ /**
62
+ * 处理事件流(SSE)
63
+ */
64
+ private handleEventStream;
65
+ }
66
+ /**
67
+ * DynaPM 配置类型导入
68
+ */
69
+ interface DynaPMConfig {
70
+ adminApi?: {
71
+ enabled?: boolean;
72
+ authToken?: string;
73
+ allowedIps?: string[];
74
+ };
75
+ }
76
+ export {};
@@ -7,51 +7,82 @@ import type { Logger } from 'pino';
7
7
  export declare class Gateway {
8
8
  private config;
9
9
  private serviceManager;
10
- /** 服务映射:hostname -> 服务配置 */
11
- private services;
10
+ /** 主机名路由:hostname -> 路由映射信息 */
11
+ private hostnameRoutes;
12
+ /** 端口路由:端口 -> 路由映射信息 */
13
+ private portRoutes;
12
14
  /** 日志记录器 */
13
15
  private logger;
16
+ /** 日志配置 */
17
+ private logging;
18
+ /** 管理 API 处理器 */
19
+ private adminApi;
20
+ /** 服务启动 Promise 追踪:serviceName -> 启动完成 Promise */
21
+ private startingPromises;
14
22
  constructor(config: DynaPMConfig, logger: Logger);
15
23
  /**
16
- * 初始化服务映射
24
+ * 初始化服务映射和端口绑定
17
25
  */
18
26
  private initServices;
19
27
  /**
20
28
  * 初始化闲置检查器
21
- * 定期检查并停止闲置的服务
22
- *
23
- * 注意:
24
- * - 纯代理模式(proxyOnly)不会被停止
25
- * - 只有当服务没有活动连接且超过闲置时间时才会停止
26
- * - 这样可以避免 SSE/WebSocket 长连接被意外断开
27
29
  */
28
30
  private initIdleChecker;
31
+ /**
32
+ * 检查单个服务是否闲置
33
+ */
34
+ private checkIdleService;
35
+ /**
36
+ * 处理端口绑定请求
37
+ */
38
+ private handlePortBindingRequest;
29
39
  /**
30
40
  * 处理传入的 HTTP 请求
31
41
  */
32
42
  private handleRequest;
43
+ /**
44
+ * 启动服务并代理请求
45
+ */
46
+ private startServiceAndProxy;
47
+ /**
48
+ * 处理需要等待服务停止完成的场景
49
+ */
50
+ private handleServiceWithWait;
51
+ /**
52
+ * 处理服务正在启动中的场景
53
+ * 等待启动 Promise 完成后,如果成功则直接代理,如果失败则返回 503
54
+ */
55
+ private handleServiceWithStartPromise;
33
56
  /**
34
57
  * 处理需要启动服务的场景
35
58
  */
36
59
  private handleServiceStart;
37
60
  /**
38
61
  * 处理直接代理场景(服务已在线)
62
+ * 双向流式转发:请求体边收边发,响应体边收边回
39
63
  */
40
64
  private handleDirectProxy;
41
65
  /**
42
- * 发起代理请求并流式转发响应
66
+ * 发起代理请求并流式转发响应(用于服务启动/等待场景)
43
67
  *
44
- * @param res - uWS HttpResponse 对象
45
- * @param service - 目标服务配置
46
- * @param path - 请求路径(包含查询字符串)
47
- * @param startTime - 请求开始时间(用于日志)
48
- * @param method - HTTP 方法
49
- * @param headers - 请求头
50
- * @param body - 请求体
68
+ * 仅在服务需要启动或等待停止时使用,此时请求体已缓冲为 Buffer。
69
+ * 响应体保持流式转发。
51
70
  */
52
71
  private forwardProxyRequest;
53
72
  /**
54
73
  * 启动网关
55
74
  */
56
75
  start(): Promise<void>;
76
+ /**
77
+ * 为管理 API 创建监听器
78
+ */
79
+ private createAdminApiListener;
80
+ /**
81
+ * 为指定端口创建监听器
82
+ */
83
+ private createPortBindingListener;
84
+ /**
85
+ * 清理所有正在运行的服务
86
+ */
87
+ cleanup(): Promise<void>;
57
88
  }