@dangao/bun-server 1.2.0 → 1.4.0
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/README.md +15 -0
- package/dist/config/config-module.d.ts +17 -0
- package/dist/config/config-module.d.ts.map +1 -1
- package/dist/config/service.d.ts +18 -1
- package/dist/config/service.d.ts.map +1 -1
- package/dist/config/types.d.ts +25 -0
- package/dist/config/types.d.ts.map +1 -1
- package/dist/controller/controller.d.ts +5 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/decorators.d.ts +30 -1
- package/dist/controller/decorators.d.ts.map +1 -1
- package/dist/controller/index.d.ts +2 -2
- package/dist/controller/index.d.ts.map +1 -1
- package/dist/controller/param-binder.d.ts +12 -0
- package/dist/controller/param-binder.d.ts.map +1 -1
- package/dist/core/application.d.ts +15 -0
- package/dist/core/application.d.ts.map +1 -1
- package/dist/core/context.d.ts +1 -0
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/server.d.ts +8 -0
- package/dist/core/server.d.ts.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6487 -4178
- package/dist/microservice/config-center/config-center-module.d.ts +43 -0
- package/dist/microservice/config-center/config-center-module.d.ts.map +1 -0
- package/dist/microservice/config-center/decorators.d.ts +58 -0
- package/dist/microservice/config-center/decorators.d.ts.map +1 -0
- package/dist/microservice/config-center/index.d.ts +9 -0
- package/dist/microservice/config-center/index.d.ts.map +1 -0
- package/dist/microservice/config-center/nacos-config-center.d.ts +37 -0
- package/dist/microservice/config-center/nacos-config-center.d.ts.map +1 -0
- package/dist/microservice/config-center/nacos-decorators.d.ts +24 -0
- package/dist/microservice/config-center/nacos-decorators.d.ts.map +1 -0
- package/dist/microservice/config-center/types.d.ts +63 -0
- package/dist/microservice/config-center/types.d.ts.map +1 -0
- package/dist/microservice/governance/circuit-breaker.d.ts +54 -0
- package/dist/microservice/governance/circuit-breaker.d.ts.map +1 -0
- package/dist/microservice/governance/decorators.d.ts +51 -0
- package/dist/microservice/governance/decorators.d.ts.map +1 -0
- package/dist/microservice/governance/index.d.ts +9 -0
- package/dist/microservice/governance/index.d.ts.map +1 -0
- package/dist/microservice/governance/rate-limiter.d.ts +26 -0
- package/dist/microservice/governance/rate-limiter.d.ts.map +1 -0
- package/dist/microservice/governance/redis-rate-limiter.d.ts +76 -0
- package/dist/microservice/governance/redis-rate-limiter.d.ts.map +1 -0
- package/dist/microservice/governance/retry-strategy.d.ts +21 -0
- package/dist/microservice/governance/retry-strategy.d.ts.map +1 -0
- package/dist/microservice/governance/types.d.ts +212 -0
- package/dist/microservice/governance/types.d.ts.map +1 -0
- package/dist/microservice/index.d.ts +10 -0
- package/dist/microservice/index.d.ts.map +1 -0
- package/dist/microservice/monitoring/index.d.ts +4 -0
- package/dist/microservice/monitoring/index.d.ts.map +1 -0
- package/dist/microservice/monitoring/metrics-collector.d.ts +54 -0
- package/dist/microservice/monitoring/metrics-collector.d.ts.map +1 -0
- package/dist/microservice/monitoring/metrics-integration.d.ts +24 -0
- package/dist/microservice/monitoring/metrics-integration.d.ts.map +1 -0
- package/dist/microservice/monitoring/types.d.ts +99 -0
- package/dist/microservice/monitoring/types.d.ts.map +1 -0
- package/dist/microservice/service-client/call-decorators.d.ts +52 -0
- package/dist/microservice/service-client/call-decorators.d.ts.map +1 -0
- package/dist/microservice/service-client/decorators.d.ts +35 -0
- package/dist/microservice/service-client/decorators.d.ts.map +1 -0
- package/dist/microservice/service-client/index.d.ts +7 -0
- package/dist/microservice/service-client/index.d.ts.map +1 -0
- package/dist/microservice/service-client/interceptors.d.ts +96 -0
- package/dist/microservice/service-client/interceptors.d.ts.map +1 -0
- package/dist/microservice/service-client/load-balancer.d.ts +59 -0
- package/dist/microservice/service-client/load-balancer.d.ts.map +1 -0
- package/dist/microservice/service-client/service-client.d.ts +74 -0
- package/dist/microservice/service-client/service-client.d.ts.map +1 -0
- package/dist/microservice/service-client/types.d.ts +155 -0
- package/dist/microservice/service-client/types.d.ts.map +1 -0
- package/dist/microservice/service-registry/decorators.d.ts +84 -0
- package/dist/microservice/service-registry/decorators.d.ts.map +1 -0
- package/dist/microservice/service-registry/discovery-decorators.d.ts +58 -0
- package/dist/microservice/service-registry/discovery-decorators.d.ts.map +1 -0
- package/dist/microservice/service-registry/health-integration.d.ts +32 -0
- package/dist/microservice/service-registry/health-integration.d.ts.map +1 -0
- package/dist/microservice/service-registry/index.d.ts +10 -0
- package/dist/microservice/service-registry/index.d.ts.map +1 -0
- package/dist/microservice/service-registry/nacos-service-registry.d.ts +68 -0
- package/dist/microservice/service-registry/nacos-service-registry.d.ts.map +1 -0
- package/dist/microservice/service-registry/service-registry-module.d.ts +48 -0
- package/dist/microservice/service-registry/service-registry-module.d.ts.map +1 -0
- package/dist/microservice/service-registry/types.d.ts +121 -0
- package/dist/microservice/service-registry/types.d.ts.map +1 -0
- package/dist/microservice/tracing/collectors.d.ts +27 -0
- package/dist/microservice/tracing/collectors.d.ts.map +1 -0
- package/dist/microservice/tracing/index.d.ts +4 -0
- package/dist/microservice/tracing/index.d.ts.map +1 -0
- package/dist/microservice/tracing/tracer.d.ts +59 -0
- package/dist/microservice/tracing/tracer.d.ts.map +1 -0
- package/dist/microservice/tracing/types.d.ts +179 -0
- package/dist/microservice/tracing/types.d.ts.map +1 -0
- package/dist/request/request.d.ts +1 -0
- package/dist/request/request.d.ts.map +1 -1
- package/docs/microservice-config-center.md +258 -0
- package/docs/microservice-nacos.md +346 -0
- package/docs/microservice-service-registry.md +306 -0
- package/docs/microservice.md +680 -0
- package/docs/troubleshooting.md +41 -0
- package/docs/zh/troubleshooting.md +41 -0
- package/package.json +5 -4
- package/src/config/config-module.ts +210 -0
- package/src/config/service.ts +52 -1
- package/src/config/types.ts +31 -0
- package/src/controller/controller.ts +8 -0
- package/src/controller/decorators.ts +55 -0
- package/src/controller/index.ts +16 -2
- package/src/controller/param-binder.ts +87 -1
- package/src/core/application.ts +100 -2
- package/src/core/context.ts +1 -0
- package/src/core/server.ts +14 -0
- package/src/index.ts +98 -2
- package/src/microservice/config-center/config-center-module.ts +98 -0
- package/src/microservice/config-center/decorators.ts +159 -0
- package/src/microservice/config-center/index.ts +13 -0
- package/src/microservice/config-center/nacos-config-center.ts +126 -0
- package/src/microservice/config-center/nacos-decorators.ts +34 -0
- package/src/microservice/config-center/types.ts +80 -0
- package/src/microservice/governance/circuit-breaker.ts +229 -0
- package/src/microservice/governance/decorators.ts +113 -0
- package/src/microservice/governance/index.ts +18 -0
- package/src/microservice/governance/rate-limiter.ts +72 -0
- package/src/microservice/governance/redis-rate-limiter.ts +154 -0
- package/src/microservice/governance/retry-strategy.ts +74 -0
- package/src/microservice/governance/types.ts +247 -0
- package/src/microservice/index.ts +12 -0
- package/src/microservice/monitoring/index.ts +8 -0
- package/src/microservice/monitoring/metrics-collector.ts +223 -0
- package/src/microservice/monitoring/metrics-integration.ts +154 -0
- package/src/microservice/monitoring/types.ts +118 -0
- package/src/microservice/service-client/call-decorators.ts +107 -0
- package/src/microservice/service-client/decorators.ts +87 -0
- package/src/microservice/service-client/index.ts +37 -0
- package/src/microservice/service-client/interceptors.ts +182 -0
- package/src/microservice/service-client/load-balancer.ts +205 -0
- package/src/microservice/service-client/service-client.ts +488 -0
- package/src/microservice/service-client/types.ts +186 -0
- package/src/microservice/service-registry/decorators.ts +238 -0
- package/src/microservice/service-registry/discovery-decorators.ts +156 -0
- package/src/microservice/service-registry/health-integration.ts +146 -0
- package/src/microservice/service-registry/index.ts +20 -0
- package/src/microservice/service-registry/nacos-service-registry.ts +259 -0
- package/src/microservice/service-registry/service-registry-module.ts +105 -0
- package/src/microservice/service-registry/types.ts +149 -0
- package/src/microservice/tracing/collectors.ts +50 -0
- package/src/microservice/tracing/index.ts +15 -0
- package/src/microservice/tracing/tracer.ts +293 -0
- package/src/microservice/tracing/types.ts +213 -0
- package/src/request/request.ts +1 -0
- package/tests/config/set-value-by-path.test.ts +53 -0
- package/tests/controller/param-map.test.ts +237 -0
- package/tests/microservice/config-center.test.ts +77 -0
- package/tests/microservice/governance.test.ts +157 -0
- package/tests/microservice/monitoring.test.ts +75 -0
- package/tests/microservice/service-client.test.ts +136 -0
- package/tests/microservice/service-registry.test.ts +80 -0
- package/tests/microservice/tracing.test.ts +143 -0
- package/tests/utils/test-port.ts +29 -19
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export { ServiceRegistryModule } from './service-registry-module';
|
|
2
|
+
export type { ServiceRegistryModuleOptions, ServiceRegistryProvider, NacosServiceRegistryOptions } from './service-registry-module';
|
|
3
|
+
export { NacosServiceRegistry } from './nacos-service-registry';
|
|
4
|
+
export { SERVICE_REGISTRY_TOKEN } from './types';
|
|
5
|
+
export type { GetInstancesOptions, InstancesChangeListener, ServiceInstance, ServiceRegistry } from './types';
|
|
6
|
+
export {
|
|
7
|
+
ServiceRegistry as ServiceRegistryDecorator,
|
|
8
|
+
getServiceRegistryMetadata,
|
|
9
|
+
registerServiceInstance,
|
|
10
|
+
deregisterServiceInstance,
|
|
11
|
+
} from './decorators';
|
|
12
|
+
export {
|
|
13
|
+
ServiceDiscovery,
|
|
14
|
+
getServiceDiscoveryMetadata,
|
|
15
|
+
initializeServiceDiscovery,
|
|
16
|
+
type ServiceDiscoveryMetadata,
|
|
17
|
+
} from './discovery-decorators';
|
|
18
|
+
export { ServiceRegistryHealthIntegration } from './health-integration';
|
|
19
|
+
export type { ServiceRegistryMetadata } from './decorators';
|
|
20
|
+
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { NacosClient, NacosServiceClient } from '@dangao/nacos-client';
|
|
2
|
+
import type {
|
|
3
|
+
ServiceInstance,
|
|
4
|
+
GetInstancesOptions,
|
|
5
|
+
InstancesChangeListener,
|
|
6
|
+
ServiceRegistry,
|
|
7
|
+
} from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Nacos 服务注册中心实现
|
|
11
|
+
* 实现 ServiceRegistry 接口,内部使用 @dangao/nacos-client
|
|
12
|
+
*/
|
|
13
|
+
export class NacosServiceRegistry implements ServiceRegistry {
|
|
14
|
+
private readonly client: NacosClient;
|
|
15
|
+
private readonly serviceClient: NacosServiceClient;
|
|
16
|
+
private readonly watchers: Map<string, { listener: InstancesChangeListener; intervalId: number }> = new Map();
|
|
17
|
+
private readonly watchInterval: number = 5000; // 默认 5 秒轮询一次
|
|
18
|
+
private readonly heartbeatInterval: number = 5000; // 默认 5 秒发送一次心跳
|
|
19
|
+
private heartbeatTimers: Map<string, number> = new Map();
|
|
20
|
+
|
|
21
|
+
public constructor(
|
|
22
|
+
client: NacosClient,
|
|
23
|
+
options?: {
|
|
24
|
+
/**
|
|
25
|
+
* 服务实例变更监听轮询间隔(毫秒)
|
|
26
|
+
* @default 5000
|
|
27
|
+
*/
|
|
28
|
+
watchInterval?: number;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 心跳间隔(毫秒)
|
|
32
|
+
* @default 5000
|
|
33
|
+
*/
|
|
34
|
+
heartbeatInterval?: number;
|
|
35
|
+
},
|
|
36
|
+
) {
|
|
37
|
+
this.client = client;
|
|
38
|
+
this.serviceClient = new NacosServiceClient(client);
|
|
39
|
+
this.watchInterval = options?.watchInterval ?? 5000;
|
|
40
|
+
this.heartbeatInterval = options?.heartbeatInterval ?? 5000;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 注册服务实例
|
|
45
|
+
*/
|
|
46
|
+
public async register(instance: ServiceInstance): Promise<void> {
|
|
47
|
+
await this.serviceClient.registerInstance({
|
|
48
|
+
serviceName: instance.serviceName,
|
|
49
|
+
ip: instance.ip,
|
|
50
|
+
port: instance.port,
|
|
51
|
+
weight: instance.weight,
|
|
52
|
+
enabled: instance.enabled,
|
|
53
|
+
metadata: instance.metadata,
|
|
54
|
+
clusterName: instance.clusterName,
|
|
55
|
+
namespaceId: instance.namespaceId,
|
|
56
|
+
groupName: instance.groupName,
|
|
57
|
+
heartBeat: false,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// 启动心跳机制
|
|
61
|
+
this.startHeartbeat(instance);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 注销服务实例
|
|
66
|
+
*/
|
|
67
|
+
public async deregister(instance: ServiceInstance): Promise<void> {
|
|
68
|
+
// 停止心跳
|
|
69
|
+
this.stopHeartbeat(instance);
|
|
70
|
+
|
|
71
|
+
await this.serviceClient.deregisterInstance(instance.serviceName, instance.ip, instance.port, {
|
|
72
|
+
namespaceId: instance.namespaceId,
|
|
73
|
+
groupName: instance.groupName,
|
|
74
|
+
clusterName: instance.clusterName,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 续约服务实例(心跳)
|
|
80
|
+
*/
|
|
81
|
+
public async renew(instance: ServiceInstance): Promise<void> {
|
|
82
|
+
await this.serviceClient.registerInstance({
|
|
83
|
+
serviceName: instance.serviceName,
|
|
84
|
+
ip: instance.ip,
|
|
85
|
+
port: instance.port,
|
|
86
|
+
weight: instance.weight,
|
|
87
|
+
enabled: instance.enabled,
|
|
88
|
+
metadata: instance.metadata,
|
|
89
|
+
clusterName: instance.clusterName,
|
|
90
|
+
namespaceId: instance.namespaceId,
|
|
91
|
+
groupName: instance.groupName,
|
|
92
|
+
heartBeat: true,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 查询服务实例列表
|
|
98
|
+
*/
|
|
99
|
+
public async getInstances(
|
|
100
|
+
serviceName: string,
|
|
101
|
+
options?: GetInstancesOptions,
|
|
102
|
+
): Promise<ServiceInstance[]> {
|
|
103
|
+
const instances = await this.serviceClient.getInstances({
|
|
104
|
+
serviceName,
|
|
105
|
+
namespaceId: options?.namespaceId,
|
|
106
|
+
groupName: options?.groupName,
|
|
107
|
+
clusterName: options?.clusterName,
|
|
108
|
+
healthyOnly: options?.healthyOnly,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return instances.map((instance) => ({
|
|
112
|
+
serviceName: instance.serviceName,
|
|
113
|
+
ip: instance.ip,
|
|
114
|
+
port: instance.port,
|
|
115
|
+
weight: instance.weight,
|
|
116
|
+
healthy: instance.healthy,
|
|
117
|
+
enabled: instance.enabled,
|
|
118
|
+
metadata: instance.metadata,
|
|
119
|
+
clusterName: instance.clusterName,
|
|
120
|
+
namespaceId: instance.namespaceId,
|
|
121
|
+
groupName: instance.groupName,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 监听服务实例变更
|
|
127
|
+
* 通过轮询实现服务实例变更监听(Nacos 3.X 移除 UDP 推送)
|
|
128
|
+
*/
|
|
129
|
+
public watchInstances(
|
|
130
|
+
serviceName: string,
|
|
131
|
+
listener: InstancesChangeListener,
|
|
132
|
+
options?: GetInstancesOptions,
|
|
133
|
+
): () => void {
|
|
134
|
+
const key = this.getWatchKey(serviceName, options);
|
|
135
|
+
|
|
136
|
+
// 如果已经存在监听器,先取消
|
|
137
|
+
const existing = this.watchers.get(key);
|
|
138
|
+
if (existing) {
|
|
139
|
+
clearInterval(existing.intervalId);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const intervalId = setInterval(async () => {
|
|
143
|
+
try {
|
|
144
|
+
const instances = await this.getInstances(serviceName, options);
|
|
145
|
+
listener(instances);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
// 监听错误不抛出,避免影响其他监听器
|
|
148
|
+
console.error(`[NacosServiceRegistry] Failed to watch instances ${serviceName}:`, error);
|
|
149
|
+
}
|
|
150
|
+
}, this.watchInterval) as unknown as number;
|
|
151
|
+
|
|
152
|
+
// 立即获取一次实例列表
|
|
153
|
+
this.getInstances(serviceName, options)
|
|
154
|
+
.then((instances) => {
|
|
155
|
+
listener(instances);
|
|
156
|
+
})
|
|
157
|
+
.catch((error) => {
|
|
158
|
+
console.error(`[NacosServiceRegistry] Failed to get initial instances ${serviceName}:`, error);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
this.watchers.set(key, { listener, intervalId });
|
|
162
|
+
|
|
163
|
+
// 返回取消监听的函数
|
|
164
|
+
return () => {
|
|
165
|
+
const watcher = this.watchers.get(key);
|
|
166
|
+
if (watcher) {
|
|
167
|
+
clearInterval(watcher.intervalId);
|
|
168
|
+
this.watchers.delete(key);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* 关闭注册中心连接
|
|
175
|
+
*/
|
|
176
|
+
public async close(): Promise<void> {
|
|
177
|
+
// 清除所有监听器
|
|
178
|
+
for (const watcher of this.watchers.values()) {
|
|
179
|
+
clearInterval(watcher.intervalId);
|
|
180
|
+
}
|
|
181
|
+
this.watchers.clear();
|
|
182
|
+
|
|
183
|
+
// 清除所有心跳定时器
|
|
184
|
+
for (const timerId of this.heartbeatTimers.values()) {
|
|
185
|
+
clearInterval(timerId);
|
|
186
|
+
}
|
|
187
|
+
this.heartbeatTimers.clear();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 启动心跳机制
|
|
192
|
+
*/
|
|
193
|
+
private startHeartbeat(instance: ServiceInstance): void {
|
|
194
|
+
const key = this.getInstanceKey(instance);
|
|
195
|
+
|
|
196
|
+
// 如果已经存在心跳,先停止
|
|
197
|
+
const existing = this.heartbeatTimers.get(key);
|
|
198
|
+
if (existing) {
|
|
199
|
+
clearInterval(existing);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const timerId = setInterval(async () => {
|
|
203
|
+
try {
|
|
204
|
+
await this.renew(instance);
|
|
205
|
+
} catch (error) {
|
|
206
|
+
console.error(`[NacosServiceRegistry] Failed to send heartbeat for ${instance.serviceName}:`, error);
|
|
207
|
+
// 心跳失败时,尝试重新注册
|
|
208
|
+
try {
|
|
209
|
+
await this.register(instance);
|
|
210
|
+
} catch (registerError) {
|
|
211
|
+
console.error(`[NacosServiceRegistry] Failed to re-register ${instance.serviceName}:`, registerError);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}, this.heartbeatInterval) as unknown as number;
|
|
215
|
+
|
|
216
|
+
this.heartbeatTimers.set(key, timerId);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 停止心跳机制
|
|
221
|
+
*/
|
|
222
|
+
private stopHeartbeat(instance: ServiceInstance): void {
|
|
223
|
+
const key = this.getInstanceKey(instance);
|
|
224
|
+
const timerId = this.heartbeatTimers.get(key);
|
|
225
|
+
if (timerId) {
|
|
226
|
+
clearInterval(timerId);
|
|
227
|
+
this.heartbeatTimers.delete(key);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 生成监听器 key
|
|
233
|
+
*/
|
|
234
|
+
private getWatchKey(serviceName: string, options?: GetInstancesOptions): string {
|
|
235
|
+
const parts = [
|
|
236
|
+
options?.namespaceId ?? 'default',
|
|
237
|
+
options?.groupName ?? 'DEFAULT_GROUP',
|
|
238
|
+
options?.clusterName ?? 'DEFAULT',
|
|
239
|
+
serviceName,
|
|
240
|
+
];
|
|
241
|
+
return parts.join(':');
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* 生成实例 key
|
|
246
|
+
*/
|
|
247
|
+
private getInstanceKey(instance: ServiceInstance): string {
|
|
248
|
+
const parts = [
|
|
249
|
+
instance.namespaceId ?? 'default',
|
|
250
|
+
instance.groupName ?? 'DEFAULT_GROUP',
|
|
251
|
+
instance.clusterName ?? 'DEFAULT',
|
|
252
|
+
instance.serviceName,
|
|
253
|
+
instance.ip,
|
|
254
|
+
instance.port.toString(),
|
|
255
|
+
];
|
|
256
|
+
return parts.join(':');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Module, MODULE_METADATA_KEY, type ModuleProvider } from '../../di/module';
|
|
2
|
+
import { NacosClient } from '@dangao/nacos-client';
|
|
3
|
+
import type { NacosClientOptions } from '@dangao/nacos-client';
|
|
4
|
+
import { NacosServiceRegistry } from './nacos-service-registry';
|
|
5
|
+
import { SERVICE_REGISTRY_TOKEN, type ServiceRegistry } from './types';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 服务注册中心 Provider 类型
|
|
9
|
+
*/
|
|
10
|
+
export type ServiceRegistryProvider = 'nacos' | 'consul' | 'eureka' | 'etcd';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Nacos 服务注册中心选项
|
|
14
|
+
*/
|
|
15
|
+
export interface NacosServiceRegistryOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Nacos 客户端配置
|
|
18
|
+
*/
|
|
19
|
+
client: NacosClientOptions;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 服务实例变更监听轮询间隔(毫秒)
|
|
23
|
+
* @default 5000
|
|
24
|
+
*/
|
|
25
|
+
watchInterval?: number;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 心跳间隔(毫秒)
|
|
29
|
+
* @default 5000
|
|
30
|
+
*/
|
|
31
|
+
heartbeatInterval?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 服务注册中心模块选项
|
|
36
|
+
*/
|
|
37
|
+
export interface ServiceRegistryModuleOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Provider 类型
|
|
40
|
+
*/
|
|
41
|
+
provider: ServiceRegistryProvider;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Nacos 配置(当 provider 为 'nacos' 时使用)
|
|
45
|
+
*/
|
|
46
|
+
nacos?: NacosServiceRegistryOptions;
|
|
47
|
+
|
|
48
|
+
// 未来可以添加其他 provider 的配置
|
|
49
|
+
// consul?: ConsulServiceRegistryOptions;
|
|
50
|
+
// eureka?: EurekaServiceRegistryOptions;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 服务注册中心模块
|
|
55
|
+
*/
|
|
56
|
+
@Module({
|
|
57
|
+
providers: [],
|
|
58
|
+
})
|
|
59
|
+
export class ServiceRegistryModule {
|
|
60
|
+
/**
|
|
61
|
+
* 创建服务注册中心模块
|
|
62
|
+
* @param options - 模块配置
|
|
63
|
+
*/
|
|
64
|
+
public static forRoot(options: ServiceRegistryModuleOptions): typeof ServiceRegistryModule {
|
|
65
|
+
const providers: ModuleProvider[] = [];
|
|
66
|
+
|
|
67
|
+
let serviceRegistry: ServiceRegistry;
|
|
68
|
+
|
|
69
|
+
switch (options.provider) {
|
|
70
|
+
case 'nacos':
|
|
71
|
+
if (!options.nacos) {
|
|
72
|
+
throw new Error('Nacos configuration is required when provider is "nacos"');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const nacosClient = new NacosClient(options.nacos.client);
|
|
76
|
+
serviceRegistry = new NacosServiceRegistry(nacosClient, {
|
|
77
|
+
watchInterval: options.nacos.watchInterval,
|
|
78
|
+
heartbeatInterval: options.nacos.heartbeatInterval,
|
|
79
|
+
});
|
|
80
|
+
break;
|
|
81
|
+
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Unsupported service registry provider: ${options.provider}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
providers.push({
|
|
87
|
+
provide: SERVICE_REGISTRY_TOKEN,
|
|
88
|
+
useValue: serviceRegistry,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const existingMetadata = Reflect.getMetadata(MODULE_METADATA_KEY, ServiceRegistryModule) || {};
|
|
92
|
+
const metadata = {
|
|
93
|
+
...existingMetadata,
|
|
94
|
+
providers: [...(existingMetadata.providers || []), ...providers],
|
|
95
|
+
exports: [
|
|
96
|
+
...(existingMetadata.exports || []),
|
|
97
|
+
SERVICE_REGISTRY_TOKEN,
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
Reflect.defineMetadata(MODULE_METADATA_KEY, metadata, ServiceRegistryModule);
|
|
101
|
+
|
|
102
|
+
return ServiceRegistryModule;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 服务注册中心抽象接口
|
|
3
|
+
* 定义服务注册与发现的核心能力,不依赖具体实现
|
|
4
|
+
*/
|
|
5
|
+
export interface ServiceRegistry {
|
|
6
|
+
/**
|
|
7
|
+
* 注册服务实例
|
|
8
|
+
* @param instance - 服务实例信息
|
|
9
|
+
*/
|
|
10
|
+
register(instance: ServiceInstance): Promise<void>;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 注销服务实例
|
|
14
|
+
* @param instance - 服务实例信息
|
|
15
|
+
*/
|
|
16
|
+
deregister(instance: ServiceInstance): Promise<void>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 续约服务实例(心跳)
|
|
20
|
+
* @param instance - 服务实例信息
|
|
21
|
+
*/
|
|
22
|
+
renew(instance: ServiceInstance): Promise<void>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 查询服务实例列表
|
|
26
|
+
* @param serviceName - 服务名
|
|
27
|
+
* @param options - 查询选项
|
|
28
|
+
* @returns 服务实例列表
|
|
29
|
+
*/
|
|
30
|
+
getInstances(
|
|
31
|
+
serviceName: string,
|
|
32
|
+
options?: GetInstancesOptions,
|
|
33
|
+
): Promise<ServiceInstance[]>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 监听服务实例变更
|
|
37
|
+
* @param serviceName - 服务名
|
|
38
|
+
* @param listener - 变更监听器
|
|
39
|
+
* @param options - 查询选项(可选)
|
|
40
|
+
* @returns 取消监听的函数
|
|
41
|
+
*/
|
|
42
|
+
watchInstances(
|
|
43
|
+
serviceName: string,
|
|
44
|
+
listener: InstancesChangeListener,
|
|
45
|
+
options?: GetInstancesOptions,
|
|
46
|
+
): () => void;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 关闭注册中心连接
|
|
50
|
+
*/
|
|
51
|
+
close(): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 服务实例信息
|
|
56
|
+
*/
|
|
57
|
+
export interface ServiceInstance {
|
|
58
|
+
/**
|
|
59
|
+
* 服务名
|
|
60
|
+
*/
|
|
61
|
+
serviceName: string;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* 实例 IP
|
|
65
|
+
*/
|
|
66
|
+
ip: string;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 实例端口
|
|
70
|
+
*/
|
|
71
|
+
port: number;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 权重(可选)
|
|
75
|
+
*/
|
|
76
|
+
weight?: number;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* 是否健康(可选)
|
|
80
|
+
*/
|
|
81
|
+
healthy?: boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 是否启用(可选)
|
|
85
|
+
*/
|
|
86
|
+
enabled?: boolean;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 元数据(可选)
|
|
90
|
+
*/
|
|
91
|
+
metadata?: Record<string, string>;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* 集群名称(可选)
|
|
95
|
+
*/
|
|
96
|
+
clusterName?: string;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* 命名空间 ID(可选)
|
|
100
|
+
*/
|
|
101
|
+
namespaceId?: string;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* 分组名称(可选)
|
|
105
|
+
*/
|
|
106
|
+
groupName?: string;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 服务实例查询选项
|
|
111
|
+
*/
|
|
112
|
+
export interface GetInstancesOptions {
|
|
113
|
+
/**
|
|
114
|
+
* 命名空间 ID(可选)
|
|
115
|
+
*/
|
|
116
|
+
namespaceId?: string;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* 分组名称(可选)
|
|
120
|
+
*/
|
|
121
|
+
groupName?: string;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* 集群名称(可选)
|
|
125
|
+
*/
|
|
126
|
+
clusterName?: string;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* 是否只返回健康实例(可选)
|
|
130
|
+
*/
|
|
131
|
+
healthyOnly?: boolean;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 服务实例变更监听器
|
|
136
|
+
*/
|
|
137
|
+
export interface InstancesChangeListener {
|
|
138
|
+
/**
|
|
139
|
+
* 服务实例变更回调
|
|
140
|
+
* @param instances - 新的服务实例列表
|
|
141
|
+
*/
|
|
142
|
+
(instances: ServiceInstance[]): void;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* ServiceRegistry Token(用于依赖注入)
|
|
147
|
+
*/
|
|
148
|
+
export const SERVICE_REGISTRY_TOKEN = Symbol('SERVICE_REGISTRY_TOKEN');
|
|
149
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { Span, TraceCollector } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 控制台追踪收集器(用于调试)
|
|
5
|
+
*/
|
|
6
|
+
export class ConsoleTraceCollector implements TraceCollector {
|
|
7
|
+
public collect(span: Span): void {
|
|
8
|
+
console.log('[Trace]', {
|
|
9
|
+
traceId: span.context.traceId,
|
|
10
|
+
spanId: span.context.spanId,
|
|
11
|
+
name: span.name,
|
|
12
|
+
duration: span.duration,
|
|
13
|
+
status: span.status,
|
|
14
|
+
tags: span.tags,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 内存追踪收集器(用于测试和开发)
|
|
21
|
+
*/
|
|
22
|
+
export class MemoryTraceCollector implements TraceCollector {
|
|
23
|
+
private readonly spans: Span[] = [];
|
|
24
|
+
|
|
25
|
+
public collect(span: Span): void {
|
|
26
|
+
this.spans.push(span);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 获取所有收集的 Span
|
|
31
|
+
*/
|
|
32
|
+
public getSpans(): Span[] {
|
|
33
|
+
return [...this.spans];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 清空收集的 Span
|
|
38
|
+
*/
|
|
39
|
+
public clear(): void {
|
|
40
|
+
this.spans.length = 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 获取指定 Trace ID 的所有 Span
|
|
45
|
+
*/
|
|
46
|
+
public getSpansByTraceId(traceId: string): Span[] {
|
|
47
|
+
return this.spans.filter((span) => span.context.traceId === traceId);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { Tracer } from './tracer';
|
|
2
|
+
export { ConsoleTraceCollector, MemoryTraceCollector } from './collectors';
|
|
3
|
+
export {
|
|
4
|
+
SpanStatus,
|
|
5
|
+
SpanKind,
|
|
6
|
+
type TraceId,
|
|
7
|
+
type SpanId,
|
|
8
|
+
type SpanContext,
|
|
9
|
+
type Span,
|
|
10
|
+
type SpanTags,
|
|
11
|
+
type SpanEvent,
|
|
12
|
+
type TracingOptions,
|
|
13
|
+
type TraceCollector,
|
|
14
|
+
} from './types';
|
|
15
|
+
|