dynapm 1.0.11 → 1.0.13
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 +37 -0
- package/README.md +8 -3
- package/README_zh.md +8 -3
- package/dist/src/config/types.d.ts +52 -1
- package/dist/src/core/admin-api.d.ts +72 -0
- package/dist/src/core/gateway.d.ts +43 -6
- package/dist/src/index.js +968 -157
- package/dist/src/utils/format.d.ts +6 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,43 @@
|
|
|
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.13] - 2026-02-10
|
|
9
|
+
|
|
10
|
+
### 🚀 性能优化
|
|
11
|
+
- **重大性能提升**:使用 undici 替代原生 http 模块作为 HTTP 客户端
|
|
12
|
+
- 吞吐量提升 **28.2%**:4345 → 5571 req/s
|
|
13
|
+
- 延迟保持 11.4ms(无退化)
|
|
14
|
+
- 使用 `undici.request()` API 实现流式转发
|
|
15
|
+
- 避免了 `undici.stream()` + Writable stream 的包装开销
|
|
16
|
+
|
|
17
|
+
### 🔧 改进
|
|
18
|
+
- 移除不再使用的 http/https 模块相关代码
|
|
19
|
+
- 清理 RouteMapping 中的冗余字段(isHttps、httpModule、httpAgent)
|
|
20
|
+
- 代码更简洁,维护性更好
|
|
21
|
+
|
|
22
|
+
### 📚 技术细节
|
|
23
|
+
- undici 的 `request()` API 比 `stream()` API 更适合代理场景
|
|
24
|
+
- `stream()` 适用于消费响应(写入文件、解析 JSON)
|
|
25
|
+
- `request()` 返回 Readable stream,可以手动控制流式转发
|
|
26
|
+
- 完全保持流式处理,客户端延迟无增加
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## [1.0.12] - 2026-02-10
|
|
31
|
+
|
|
32
|
+
### ✨ 新增
|
|
33
|
+
- 添加 `proxyOnly` 配置项,支持纯反向代理模式
|
|
34
|
+
- 不管理服务生命周期(启动/停止)
|
|
35
|
+
- 仅做请求转发,适合已运行的服务
|
|
36
|
+
|
|
37
|
+
### 🔧 改进
|
|
38
|
+
- WebSocket 代理正确转发客户端请求路径
|
|
39
|
+
- WebSocket 代理完整转发客户端请求头(Cookie、Authorization 等)
|
|
40
|
+
- 改进 WebSocket 错误处理,避免连接重试循环
|
|
41
|
+
- 添加 TypeScript 测试配置支持
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
8
45
|
## [1.0.11] - 2025-02-10
|
|
9
46
|
|
|
10
47
|
### 🔧 修复
|
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
|
-
[](https://www.npmjs.com/package/dynapm)
|
|
8
|
-

|
|
9
|
-

|
|
7
|
+
[](https://www.npmjs.com/package/dynapm)  
|
|
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
|
|
|
@@ -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',
|
package/README_zh.md
CHANGED
|
@@ -4,9 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> **动态进程管理器** - 具有类 serverless 特性的轻量级通用服务管理系统
|
|
6
6
|
|
|
7
|
-
[](https://www.npmjs.com/package/dynapm)
|
|
8
|
-

|
|
9
|
-

|
|
7
|
+
[](https://www.npmjs.com/package/dynapm)  
|
|
10
8
|
|
|
11
9
|
DynaPM 是**复杂容器编排平台(如 Knative、Sablier)的轻量级替代方案**,专为私有化部署设计。它通过按需启动和闲置自动停止的方式,帮助你在资源受限的服务器上管理数百个低频访问的服务。
|
|
12
10
|
|
|
@@ -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',
|
|
@@ -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
|
/** 服务标识 */
|
|
@@ -44,16 +53,54 @@ export interface ServiceConfig {
|
|
|
44
53
|
commands: ServiceCommands;
|
|
45
54
|
/** 健康检查配置 */
|
|
46
55
|
healthCheck?: HealthCheckConfig;
|
|
56
|
+
/** 纯代理模式:只做反向代理,不启动/停止服务 */
|
|
57
|
+
proxyOnly?: boolean;
|
|
58
|
+
/** Hostname 映射(可选):配置后可通过此 hostname 访问 */
|
|
59
|
+
host?: string;
|
|
60
|
+
/** 专属端口(可选):配置后网关会监听此端口 */
|
|
61
|
+
port?: number;
|
|
62
|
+
/** 路由配置(可选):配置多个访问地址 */
|
|
63
|
+
routes?: RouteConfig[];
|
|
47
64
|
/** 运行时状态(内部使用) */
|
|
48
65
|
_state?: ServiceState;
|
|
49
66
|
}
|
|
50
67
|
/** 服务运行状态 */
|
|
51
68
|
export interface ServiceState {
|
|
52
|
-
status: 'offline' | 'starting' | 'online';
|
|
69
|
+
status: 'offline' | 'starting' | 'online' | 'stopping';
|
|
53
70
|
lastAccessTime: number;
|
|
54
71
|
/** 当前活动连接数(HTTP/SSE/WebSocket) */
|
|
55
72
|
activeConnections: number;
|
|
56
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;
|
|
57
104
|
}
|
|
58
105
|
/** DynaPM全局配置 */
|
|
59
106
|
export interface DynaPMConfig {
|
|
@@ -63,4 +110,8 @@ export interface DynaPMConfig {
|
|
|
63
110
|
host?: string;
|
|
64
111
|
/** 服务映射:hostname -> 服务配置 */
|
|
65
112
|
services: Record<string, ServiceConfig>;
|
|
113
|
+
/** 管理 API 配置 */
|
|
114
|
+
adminApi?: AdminApiConfig;
|
|
115
|
+
/** 日志配置 */
|
|
116
|
+
logging?: LoggingConfig;
|
|
66
117
|
}
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
* 处理管理 API 请求
|
|
39
|
+
*/
|
|
40
|
+
handleAdminApi(res: HttpResponse, req: HttpRequest): void;
|
|
41
|
+
/**
|
|
42
|
+
* 获取服务列表
|
|
43
|
+
*/
|
|
44
|
+
private getServicesList;
|
|
45
|
+
/**
|
|
46
|
+
* 获取服务详情
|
|
47
|
+
*/
|
|
48
|
+
private getServiceDetail;
|
|
49
|
+
/**
|
|
50
|
+
* 停止服务
|
|
51
|
+
*/
|
|
52
|
+
stopService(res: HttpResponse, serviceName: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* 启动服务
|
|
55
|
+
*/
|
|
56
|
+
startService(res: HttpResponse, serviceName: string): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* 处理事件流(SSE)
|
|
59
|
+
*/
|
|
60
|
+
private handleEventStream;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* DynaPM 配置类型导入
|
|
64
|
+
*/
|
|
65
|
+
interface DynaPMConfig {
|
|
66
|
+
adminApi?: {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
authToken?: string;
|
|
69
|
+
allowedIps?: string[];
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export {};
|
|
@@ -7,27 +7,51 @@ import type { Logger } from 'pino';
|
|
|
7
7
|
export declare class Gateway {
|
|
8
8
|
private config;
|
|
9
9
|
private serviceManager;
|
|
10
|
-
/**
|
|
11
|
-
private
|
|
10
|
+
/** 主机名路由:hostname -> 路由映射信息 */
|
|
11
|
+
private hostnameRoutes;
|
|
12
|
+
/** 端口路由:端口 -> 路由映射信息 */
|
|
13
|
+
private portRoutes;
|
|
12
14
|
/** 日志记录器 */
|
|
13
15
|
private logger;
|
|
16
|
+
/** 日志配置 */
|
|
17
|
+
private logging;
|
|
18
|
+
/** 管理 API 处理器 */
|
|
19
|
+
private adminApi;
|
|
14
20
|
constructor(config: DynaPMConfig, logger: Logger);
|
|
15
21
|
/**
|
|
16
|
-
*
|
|
22
|
+
* 初始化服务映射和端口绑定
|
|
17
23
|
*/
|
|
18
24
|
private initServices;
|
|
19
25
|
/**
|
|
20
26
|
* 初始化闲置检查器
|
|
21
27
|
* 定期检查并停止闲置的服务
|
|
22
28
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
29
|
+
* 注意:
|
|
30
|
+
* - 纯代理模式(proxyOnly)不会被停止
|
|
31
|
+
* - 只有当服务没有活动连接且超过闲置时间时才会停止
|
|
32
|
+
* - 这样可以避免 SSE/WebSocket 长连接被意外断开
|
|
25
33
|
*/
|
|
26
34
|
private initIdleChecker;
|
|
35
|
+
/**
|
|
36
|
+
* 检查单个服务是否闲置
|
|
37
|
+
*/
|
|
38
|
+
private checkIdleService;
|
|
39
|
+
/**
|
|
40
|
+
* 处理端口绑定请求(直接路由,无需 Host 头)
|
|
41
|
+
*/
|
|
42
|
+
private handlePortBindingRequest;
|
|
27
43
|
/**
|
|
28
44
|
* 处理传入的 HTTP 请求
|
|
29
45
|
*/
|
|
30
46
|
private handleRequest;
|
|
47
|
+
/**
|
|
48
|
+
* 启动服务并代理请求
|
|
49
|
+
*/
|
|
50
|
+
private startServiceAndProxy;
|
|
51
|
+
/**
|
|
52
|
+
* 处理需要等待服务停止完成的场景
|
|
53
|
+
*/
|
|
54
|
+
private handleServiceWithWait;
|
|
31
55
|
/**
|
|
32
56
|
* 处理需要启动服务的场景
|
|
33
57
|
*/
|
|
@@ -40,7 +64,7 @@ export declare class Gateway {
|
|
|
40
64
|
* 发起代理请求并流式转发响应
|
|
41
65
|
*
|
|
42
66
|
* @param res - uWS HttpResponse 对象
|
|
43
|
-
* @param
|
|
67
|
+
* @param mapping - 路由映射信息(包含缓存的目标 URL)
|
|
44
68
|
* @param path - 请求路径(包含查询字符串)
|
|
45
69
|
* @param startTime - 请求开始时间(用于日志)
|
|
46
70
|
* @param method - HTTP 方法
|
|
@@ -52,4 +76,17 @@ export declare class Gateway {
|
|
|
52
76
|
* 启动网关
|
|
53
77
|
*/
|
|
54
78
|
start(): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* 为管理 API 创建监听器
|
|
81
|
+
*/
|
|
82
|
+
private createAdminApiListener;
|
|
83
|
+
/**
|
|
84
|
+
* 为指定端口创建监听器
|
|
85
|
+
*/
|
|
86
|
+
private createPortBindingListener;
|
|
87
|
+
/**
|
|
88
|
+
* 清理所有正在运行的服务
|
|
89
|
+
* 在网关退出时调用
|
|
90
|
+
*/
|
|
91
|
+
cleanup(): Promise<void>;
|
|
55
92
|
}
|