@dangao/bun-server 1.3.0 → 1.5.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/core/application.d.ts +42 -1
- 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 +33 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6510 -4164
- 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/core/application.ts +189 -3
- package/src/core/context.ts +1 -0
- package/src/core/server.ts +128 -2
- package/src/index.ts +81 -0
- 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/core/graceful-shutdown.test.ts +321 -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,680 @@
|
|
|
1
|
+
# 微服务架构支持
|
|
2
|
+
|
|
3
|
+
Bun Server Framework 提供了完整的微服务架构支持,包括配置中心、服务注册与发现、服务调用、服务治理和可观测性等功能。
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
- [快速开始](#快速开始)
|
|
8
|
+
- [配置中心](#配置中心)
|
|
9
|
+
- [服务注册与发现](#服务注册与发现)
|
|
10
|
+
- [服务调用](#服务调用)
|
|
11
|
+
- [服务治理](#服务治理)
|
|
12
|
+
- [监控和追踪](#监控和追踪)
|
|
13
|
+
- [最佳实践](#最佳实践)
|
|
14
|
+
|
|
15
|
+
## 快速开始
|
|
16
|
+
|
|
17
|
+
### 安装依赖
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
bun add @dangao/bun-server
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 基础示例
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { Application } from '@dangao/bun-server';
|
|
27
|
+
import {
|
|
28
|
+
ConfigCenterModule,
|
|
29
|
+
ServiceRegistryModule,
|
|
30
|
+
ServiceClient,
|
|
31
|
+
} from '@dangao/bun-server';
|
|
32
|
+
|
|
33
|
+
// 创建应用
|
|
34
|
+
const app = new Application();
|
|
35
|
+
|
|
36
|
+
// 注册配置中心模块
|
|
37
|
+
app.registerModule(
|
|
38
|
+
ConfigCenterModule.forRoot({
|
|
39
|
+
provider: 'nacos',
|
|
40
|
+
nacos: {
|
|
41
|
+
client: {
|
|
42
|
+
serverList: ['http://localhost:8848'],
|
|
43
|
+
namespaceId: 'public',
|
|
44
|
+
username: 'nacos',
|
|
45
|
+
password: 'nacos',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// 注册服务注册中心模块
|
|
52
|
+
app.registerModule(
|
|
53
|
+
ServiceRegistryModule.forRoot({
|
|
54
|
+
provider: 'nacos',
|
|
55
|
+
nacos: {
|
|
56
|
+
client: {
|
|
57
|
+
serverList: ['http://localhost:8848'],
|
|
58
|
+
namespaceId: 'public',
|
|
59
|
+
username: 'nacos',
|
|
60
|
+
password: 'nacos',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// 启动应用
|
|
67
|
+
await app.listen(3000);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 配置中心
|
|
71
|
+
|
|
72
|
+
### 基本使用
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import {
|
|
76
|
+
ConfigCenterModule,
|
|
77
|
+
CONFIG_CENTER_TOKEN,
|
|
78
|
+
type ConfigCenter,
|
|
79
|
+
} from '@dangao/bun-server';
|
|
80
|
+
import { Inject, Injectable } from '@dangao/bun-server';
|
|
81
|
+
|
|
82
|
+
@Injectable()
|
|
83
|
+
class MyService {
|
|
84
|
+
public constructor(
|
|
85
|
+
@Inject(CONFIG_CENTER_TOKEN) private readonly configCenter: ConfigCenter,
|
|
86
|
+
) {}
|
|
87
|
+
|
|
88
|
+
public async getConfig() {
|
|
89
|
+
const config = await this.configCenter.getConfig(
|
|
90
|
+
'my-config',
|
|
91
|
+
'DEFAULT_GROUP',
|
|
92
|
+
);
|
|
93
|
+
return JSON.parse(config.content);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 使用装饰器
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { ConfigCenterValue, Injectable } from '@dangao/bun-server';
|
|
102
|
+
|
|
103
|
+
@Injectable()
|
|
104
|
+
class MyService {
|
|
105
|
+
@ConfigCenterValue('my-config', 'DEFAULT_GROUP', {
|
|
106
|
+
defaultValue: 'default-value',
|
|
107
|
+
watch: true, // 监听配置变更
|
|
108
|
+
})
|
|
109
|
+
public configValue: string = '';
|
|
110
|
+
|
|
111
|
+
public getConfig() {
|
|
112
|
+
return this.configValue; // 自动从配置中心获取
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 配置热更新
|
|
118
|
+
|
|
119
|
+
配置中心支持配置热更新,当配置变更时会自动通知应用:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const configCenter = container.resolve<ConfigCenter>(CONFIG_CENTER_TOKEN);
|
|
123
|
+
|
|
124
|
+
configCenter.watchConfig('my-config', 'DEFAULT_GROUP', (newConfig) => {
|
|
125
|
+
console.log('Config updated:', newConfig.content);
|
|
126
|
+
// 更新应用配置
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### ConfigModule 集成
|
|
131
|
+
|
|
132
|
+
ConfigModule 支持与配置中心深度集成,配置变更会自动刷新:
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { ConfigModule } from '@dangao/bun-server';
|
|
136
|
+
|
|
137
|
+
ConfigModule.forRoot({
|
|
138
|
+
defaultConfig: { app: { name: 'MyApp' } },
|
|
139
|
+
configCenter: {
|
|
140
|
+
enabled: true,
|
|
141
|
+
configs: new Map([
|
|
142
|
+
['app.name', { dataId: 'app-name', groupName: 'DEFAULT_GROUP' }],
|
|
143
|
+
['app.port', { dataId: 'app-port', groupName: 'DEFAULT_GROUP' }],
|
|
144
|
+
]),
|
|
145
|
+
configCenterPriority: true, // 配置中心配置优先级最高
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 服务注册与发现
|
|
151
|
+
|
|
152
|
+
### 服务注册
|
|
153
|
+
|
|
154
|
+
#### 使用装饰器自动注册
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { ServiceRegistry, Controller, GET } from '@dangao/bun-server';
|
|
158
|
+
|
|
159
|
+
@ServiceRegistry('user-service', {
|
|
160
|
+
port: 3000,
|
|
161
|
+
weight: 100,
|
|
162
|
+
metadata: { version: '1.0.0' },
|
|
163
|
+
})
|
|
164
|
+
@Controller('/api/users')
|
|
165
|
+
class UserController {
|
|
166
|
+
@GET('/')
|
|
167
|
+
public getUsers() {
|
|
168
|
+
return { users: [] };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 应用启动时会自动注册服务
|
|
173
|
+
const app = new Application();
|
|
174
|
+
app.registerController(UserController);
|
|
175
|
+
await app.listen(3000);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### 手动注册
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
import {
|
|
182
|
+
ServiceRegistryModule,
|
|
183
|
+
SERVICE_REGISTRY_TOKEN,
|
|
184
|
+
type ServiceRegistry,
|
|
185
|
+
} from '@dangao/bun-server';
|
|
186
|
+
import { Inject, Injectable } from '@dangao/bun-server';
|
|
187
|
+
|
|
188
|
+
@Injectable()
|
|
189
|
+
class MyService {
|
|
190
|
+
public constructor(
|
|
191
|
+
@Inject(SERVICE_REGISTRY_TOKEN) private readonly registry: ServiceRegistry,
|
|
192
|
+
) {}
|
|
193
|
+
|
|
194
|
+
public async registerService() {
|
|
195
|
+
await this.registry.register({
|
|
196
|
+
serviceName: 'my-service',
|
|
197
|
+
ip: '127.0.0.1',
|
|
198
|
+
port: 3000,
|
|
199
|
+
weight: 100,
|
|
200
|
+
healthy: true,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### 服务发现
|
|
207
|
+
|
|
208
|
+
#### 使用装饰器自动发现
|
|
209
|
+
|
|
210
|
+
```typescript
|
|
211
|
+
import { ServiceDiscovery, Injectable } from '@dangao/bun-server';
|
|
212
|
+
import type { ServiceInstance } from '@dangao/bun-server';
|
|
213
|
+
|
|
214
|
+
@Injectable()
|
|
215
|
+
class MyService {
|
|
216
|
+
@ServiceDiscovery('user-service', {
|
|
217
|
+
healthyOnly: true, // 只获取健康实例
|
|
218
|
+
})
|
|
219
|
+
public instances: ServiceInstance[] = [];
|
|
220
|
+
|
|
221
|
+
public async getAvailableInstances() {
|
|
222
|
+
// instances 会自动更新
|
|
223
|
+
return this.instances;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
#### 手动发现
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
const instances = await serviceRegistry.getInstances('user-service', {
|
|
232
|
+
healthyOnly: true,
|
|
233
|
+
namespaceId: 'public',
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// 监听服务实例变更
|
|
237
|
+
serviceRegistry.watchInstances('user-service', (newInstances) => {
|
|
238
|
+
console.log('Instances updated:', newInstances);
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 健康检查集成
|
|
243
|
+
|
|
244
|
+
服务注册会自动集成健康检查模块,根据健康检查状态更新服务健康状态:
|
|
245
|
+
|
|
246
|
+
```typescript
|
|
247
|
+
import { HealthModule } from '@dangao/bun-server';
|
|
248
|
+
|
|
249
|
+
// 注册健康检查模块
|
|
250
|
+
HealthModule.forRoot({
|
|
251
|
+
indicators: [
|
|
252
|
+
{
|
|
253
|
+
name: 'db',
|
|
254
|
+
async check() {
|
|
255
|
+
// 检查数据库连接
|
|
256
|
+
return { status: 'up' };
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
// 使用 @ServiceRegistry 装饰器的服务会自动根据健康检查状态更新
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## 服务调用
|
|
266
|
+
|
|
267
|
+
### 基本使用
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import {
|
|
271
|
+
ServiceClient,
|
|
272
|
+
SERVICE_REGISTRY_TOKEN,
|
|
273
|
+
type ServiceRegistry,
|
|
274
|
+
} from '@dangao/bun-server';
|
|
275
|
+
import { Inject, Injectable } from '@dangao/bun-server';
|
|
276
|
+
|
|
277
|
+
@Injectable()
|
|
278
|
+
class MyService {
|
|
279
|
+
private readonly serviceClient: ServiceClient;
|
|
280
|
+
|
|
281
|
+
public constructor(
|
|
282
|
+
@Inject(SERVICE_REGISTRY_TOKEN) serviceRegistry: ServiceRegistry,
|
|
283
|
+
) {
|
|
284
|
+
this.serviceClient = new ServiceClient(serviceRegistry);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
public async callUserService() {
|
|
288
|
+
const response = await this.serviceClient.call({
|
|
289
|
+
serviceName: 'user-service',
|
|
290
|
+
method: 'GET',
|
|
291
|
+
path: '/api/users',
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
return response.data;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 使用装饰器注入
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { ServiceClient, Injectable } from '@dangao/bun-server';
|
|
303
|
+
|
|
304
|
+
@Injectable()
|
|
305
|
+
class MyService {
|
|
306
|
+
public constructor(
|
|
307
|
+
@ServiceClient() private readonly serviceClient: ServiceClient,
|
|
308
|
+
) {}
|
|
309
|
+
|
|
310
|
+
public async callUserService() {
|
|
311
|
+
return await this.serviceClient.call({
|
|
312
|
+
serviceName: 'user-service',
|
|
313
|
+
method: 'GET',
|
|
314
|
+
path: '/api/users',
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 负载均衡
|
|
321
|
+
|
|
322
|
+
ServiceClient 支持多种负载均衡策略:
|
|
323
|
+
|
|
324
|
+
```typescript
|
|
325
|
+
// 随机负载均衡
|
|
326
|
+
await serviceClient.call({
|
|
327
|
+
serviceName: 'user-service',
|
|
328
|
+
method: 'GET',
|
|
329
|
+
path: '/api/users',
|
|
330
|
+
loadBalanceStrategy: 'random',
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// 轮询负载均衡
|
|
334
|
+
await serviceClient.call({
|
|
335
|
+
serviceName: 'user-service',
|
|
336
|
+
method: 'GET',
|
|
337
|
+
path: '/api/users',
|
|
338
|
+
loadBalanceStrategy: 'roundRobin',
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// 加权轮询
|
|
342
|
+
await serviceClient.call({
|
|
343
|
+
serviceName: 'user-service',
|
|
344
|
+
method: 'GET',
|
|
345
|
+
path: '/api/users',
|
|
346
|
+
loadBalanceStrategy: 'weightedRoundRobin',
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// 一致性哈希(适用于需要会话粘性的场景)
|
|
350
|
+
await serviceClient.call({
|
|
351
|
+
serviceName: 'user-service',
|
|
352
|
+
method: 'GET',
|
|
353
|
+
path: '/api/users',
|
|
354
|
+
loadBalanceStrategy: 'consistentHash',
|
|
355
|
+
consistentHashKey: 'user-id-123',
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// 最少连接
|
|
359
|
+
await serviceClient.call({
|
|
360
|
+
serviceName: 'user-service',
|
|
361
|
+
method: 'GET',
|
|
362
|
+
path: '/api/users',
|
|
363
|
+
loadBalanceStrategy: 'leastActive',
|
|
364
|
+
});
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 流式调用
|
|
368
|
+
|
|
369
|
+
支持 Server-Sent Events 等流式响应:
|
|
370
|
+
|
|
371
|
+
```typescript
|
|
372
|
+
const stream = await serviceClient.callStream({
|
|
373
|
+
serviceName: 'stream-service',
|
|
374
|
+
method: 'GET',
|
|
375
|
+
path: '/api/events',
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
// 读取流数据
|
|
379
|
+
const reader = stream.getReader();
|
|
380
|
+
while (true) {
|
|
381
|
+
const { done, value } = await reader.read();
|
|
382
|
+
if (done) break;
|
|
383
|
+
console.log('Received:', new TextDecoder().decode(value));
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
### 拦截器
|
|
388
|
+
|
|
389
|
+
#### 请求拦截器
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import {
|
|
393
|
+
TraceIdRequestInterceptor,
|
|
394
|
+
RequestLogInterceptor,
|
|
395
|
+
} from '@dangao/bun-server';
|
|
396
|
+
|
|
397
|
+
serviceClient.addRequestInterceptor(new TraceIdRequestInterceptor());
|
|
398
|
+
serviceClient.addRequestInterceptor(new RequestLogInterceptor());
|
|
399
|
+
|
|
400
|
+
// 自定义请求拦截器
|
|
401
|
+
serviceClient.addRequestInterceptor({
|
|
402
|
+
async intercept(options) {
|
|
403
|
+
options.headers = {
|
|
404
|
+
...options.headers,
|
|
405
|
+
'X-Custom-Header': 'value',
|
|
406
|
+
};
|
|
407
|
+
return options;
|
|
408
|
+
},
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### 响应拦截器
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
import {
|
|
416
|
+
ResponseLogInterceptor,
|
|
417
|
+
ErrorHandlerInterceptor,
|
|
418
|
+
} from '@dangao/bun-server';
|
|
419
|
+
|
|
420
|
+
serviceClient.addResponseInterceptor(new ResponseLogInterceptor());
|
|
421
|
+
serviceClient.addResponseInterceptor(new ErrorHandlerInterceptor());
|
|
422
|
+
|
|
423
|
+
// 自定义响应拦截器
|
|
424
|
+
serviceClient.addResponseInterceptor({
|
|
425
|
+
async intercept(response) {
|
|
426
|
+
// 转换响应数据
|
|
427
|
+
return {
|
|
428
|
+
...response,
|
|
429
|
+
data: transformData(response.data),
|
|
430
|
+
};
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
## 服务治理
|
|
436
|
+
|
|
437
|
+
### 熔断器
|
|
438
|
+
|
|
439
|
+
#### 使用装饰器
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
import { CircuitBreaker, Injectable } from '@dangao/bun-server';
|
|
443
|
+
|
|
444
|
+
@Injectable()
|
|
445
|
+
class MyService {
|
|
446
|
+
@CircuitBreaker({
|
|
447
|
+
failureThreshold: 0.5,
|
|
448
|
+
timeWindow: 60000,
|
|
449
|
+
minimumRequests: 10,
|
|
450
|
+
}, 'fallbackMethod')
|
|
451
|
+
public async callExternalService() {
|
|
452
|
+
// 自动应用熔断保护
|
|
453
|
+
return await externalService.call();
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
private async fallbackMethod() {
|
|
457
|
+
return { message: 'Fallback response' };
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
#### 手动使用
|
|
463
|
+
|
|
464
|
+
```typescript
|
|
465
|
+
import { CircuitBreaker } from '@dangao/bun-server';
|
|
466
|
+
|
|
467
|
+
const circuitBreaker = new CircuitBreaker({
|
|
468
|
+
failureThreshold: 0.5,
|
|
469
|
+
timeWindow: 60000,
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
const result = await circuitBreaker.execute(
|
|
473
|
+
async () => {
|
|
474
|
+
return await serviceClient.call(options);
|
|
475
|
+
},
|
|
476
|
+
async () => {
|
|
477
|
+
// 降级处理
|
|
478
|
+
return { fallback: true };
|
|
479
|
+
},
|
|
480
|
+
);
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### 限流
|
|
484
|
+
|
|
485
|
+
#### 内存限流
|
|
486
|
+
|
|
487
|
+
```typescript
|
|
488
|
+
import { RateLimiter } from '@dangao/bun-server';
|
|
489
|
+
|
|
490
|
+
const rateLimiter = new RateLimiter({
|
|
491
|
+
requestsPerSecond: 100,
|
|
492
|
+
timeWindow: 1000,
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
const allowed = await rateLimiter.allow('service-key');
|
|
496
|
+
if (!allowed) {
|
|
497
|
+
throw new Error('Rate limit exceeded');
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
#### 分布式限流(Redis)
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
import { RedisRateLimiter } from '@dangao/bun-server';
|
|
505
|
+
|
|
506
|
+
// 需要提供 Redis 客户端
|
|
507
|
+
const redisClient = {
|
|
508
|
+
get: async (key: string) => await redis.get(key),
|
|
509
|
+
set: async (key: string, value: string, options?: any) => {
|
|
510
|
+
await redis.set(key, value, options);
|
|
511
|
+
},
|
|
512
|
+
del: async (key: string) => await redis.del(key),
|
|
513
|
+
incr: async (key: string) => await redis.incr(key),
|
|
514
|
+
expire: async (key: string, seconds: number) => {
|
|
515
|
+
await redis.expire(key, seconds);
|
|
516
|
+
},
|
|
517
|
+
exists: async (key: string) => await redis.exists(key),
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const rateLimiter = new RedisRateLimiter(
|
|
521
|
+
{ client: redisClient },
|
|
522
|
+
{
|
|
523
|
+
requestsPerSecond: 100,
|
|
524
|
+
timeWindow: 1000,
|
|
525
|
+
},
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
const allowed = await rateLimiter.allow('service-key');
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### 重试策略
|
|
532
|
+
|
|
533
|
+
```typescript
|
|
534
|
+
import {
|
|
535
|
+
FixedIntervalRetryStrategy,
|
|
536
|
+
ExponentialBackoffRetryStrategy,
|
|
537
|
+
} from '@dangao/bun-server';
|
|
538
|
+
|
|
539
|
+
// 固定间隔重试
|
|
540
|
+
const fixedRetry = new FixedIntervalRetryStrategy({
|
|
541
|
+
maxRetries: 3,
|
|
542
|
+
retryDelay: 1000,
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// 指数退避重试
|
|
546
|
+
const exponentialRetry = new ExponentialBackoffRetryStrategy({
|
|
547
|
+
maxRetries: 3,
|
|
548
|
+
baseDelay: 1000,
|
|
549
|
+
maxDelay: 30000,
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
// 在 ServiceClient 中使用
|
|
553
|
+
serviceClient.setDefaultRetryStrategy({
|
|
554
|
+
maxRetries: 3,
|
|
555
|
+
retryDelay: 1000,
|
|
556
|
+
exponentialBackoff: true,
|
|
557
|
+
shouldRetry: (error) => {
|
|
558
|
+
// 只对网络错误重试
|
|
559
|
+
return error.message.includes('timeout') || error.message.includes('network');
|
|
560
|
+
},
|
|
561
|
+
});
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
## 监控和追踪
|
|
565
|
+
|
|
566
|
+
### 分布式追踪
|
|
567
|
+
|
|
568
|
+
```typescript
|
|
569
|
+
import {
|
|
570
|
+
Tracer,
|
|
571
|
+
ConsoleTraceCollector,
|
|
572
|
+
SpanKind,
|
|
573
|
+
} from '@dangao/bun-server';
|
|
574
|
+
|
|
575
|
+
const tracer = new Tracer({
|
|
576
|
+
samplingRate: 1.0,
|
|
577
|
+
enabled: true,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
tracer.addCollector(new ConsoleTraceCollector());
|
|
581
|
+
|
|
582
|
+
// 在 ServiceClient 中使用
|
|
583
|
+
serviceClient.setTracer(tracer);
|
|
584
|
+
|
|
585
|
+
// 手动创建 Span
|
|
586
|
+
const span = tracer.startSpan('my-operation', SpanKind.INTERNAL);
|
|
587
|
+
tracer.setSpanTags(span.context.spanId, {
|
|
588
|
+
'operation.name': 'process-data',
|
|
589
|
+
'user.id': '123',
|
|
590
|
+
});
|
|
591
|
+
// ... 执行操作
|
|
592
|
+
tracer.endSpan(span.context.spanId, SpanStatus.OK);
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### 服务监控
|
|
596
|
+
|
|
597
|
+
```typescript
|
|
598
|
+
import { ServiceMetricsCollector } from '@dangao/bun-server';
|
|
599
|
+
|
|
600
|
+
const metricsCollector = new ServiceMetricsCollector({
|
|
601
|
+
enabled: true,
|
|
602
|
+
autoReportToMetrics: true, // 自动上报到 MetricsModule
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
// 在 ServiceClient 中使用
|
|
606
|
+
serviceClient.setMetricsCollector(metricsCollector);
|
|
607
|
+
|
|
608
|
+
// 查询指标
|
|
609
|
+
const allMetrics = metricsCollector.getAllMetrics();
|
|
610
|
+
const healthStatus = metricsCollector.getAllHealthStatus();
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Prometheus 集成
|
|
614
|
+
|
|
615
|
+
服务监控指标会自动上报到 MetricsModule,通过 `/metrics` 端点导出 Prometheus 格式:
|
|
616
|
+
|
|
617
|
+
```typescript
|
|
618
|
+
import { MetricsModule } from '@dangao/bun-server';
|
|
619
|
+
|
|
620
|
+
MetricsModule.forRoot({
|
|
621
|
+
enableHttpMetrics: true,
|
|
622
|
+
});
|
|
623
|
+
|
|
624
|
+
// 访问 http://localhost:3000/metrics 获取 Prometheus 格式指标
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
导出的指标包括:
|
|
628
|
+
- `service_calls_total` - 服务调用总数
|
|
629
|
+
- `service_calls_success_total` - 成功调用数
|
|
630
|
+
- `service_calls_failure_total` - 失败调用数
|
|
631
|
+
- `service_call_latency_avg_ms` - 平均延迟
|
|
632
|
+
- `service_call_latency_min_ms` - 最小延迟
|
|
633
|
+
- `service_call_latency_max_ms` - 最大延迟
|
|
634
|
+
- `service_call_error_rate` - 错误率
|
|
635
|
+
- `service_instance_healthy` - 实例健康状态
|
|
636
|
+
- `service_instance_consecutive_failures` - 连续失败次数
|
|
637
|
+
|
|
638
|
+
## 最佳实践
|
|
639
|
+
|
|
640
|
+
### 1. 配置管理
|
|
641
|
+
|
|
642
|
+
- 使用配置中心管理动态配置
|
|
643
|
+
- 为不同环境使用不同的命名空间
|
|
644
|
+
- 启用配置监听以实现热更新
|
|
645
|
+
- 设置合理的配置优先级
|
|
646
|
+
|
|
647
|
+
### 2. 服务注册
|
|
648
|
+
|
|
649
|
+
- 使用 `@ServiceRegistry` 装饰器自动注册
|
|
650
|
+
- 配置合理的服务元数据(版本、权重等)
|
|
651
|
+
- 启用健康检查集成
|
|
652
|
+
- 确保应用关闭时正确注销服务
|
|
653
|
+
|
|
654
|
+
### 3. 服务调用
|
|
655
|
+
|
|
656
|
+
- 选择合适的负载均衡策略
|
|
657
|
+
- 配置合理的超时时间
|
|
658
|
+
- 使用拦截器统一处理请求/响应
|
|
659
|
+
- 启用追踪和监控
|
|
660
|
+
|
|
661
|
+
### 4. 服务治理
|
|
662
|
+
|
|
663
|
+
- 为关键服务启用熔断器
|
|
664
|
+
- 配置合理的限流策略
|
|
665
|
+
- 实现降级处理逻辑
|
|
666
|
+
- 使用重试策略处理临时故障
|
|
667
|
+
|
|
668
|
+
### 5. 可观测性
|
|
669
|
+
|
|
670
|
+
- 启用分布式追踪
|
|
671
|
+
- 配置合理的采样率
|
|
672
|
+
- 集成 Prometheus 监控
|
|
673
|
+
- 设置告警规则
|
|
674
|
+
|
|
675
|
+
## 更多资源
|
|
676
|
+
|
|
677
|
+
- [配置中心使用指南](./microservice-config-center.md)
|
|
678
|
+
- [服务注册与发现使用指南](./microservice-service-registry.md)
|
|
679
|
+
- [Nacos 集成文档](./microservice-nacos.md)
|
|
680
|
+
|
package/docs/troubleshooting.md
CHANGED
|
@@ -99,6 +99,47 @@ const { SomeService } = await import("./some-service");
|
|
|
99
99
|
|
|
100
100
|
## Dependency Injection
|
|
101
101
|
|
|
102
|
+
### ⚠️ CRITICAL: Injected Dependencies Are Undefined
|
|
103
|
+
|
|
104
|
+
**Error**: Injected services are `undefined` at runtime, or work with `bun app.ts` but fail in VSCode debugger.
|
|
105
|
+
|
|
106
|
+
**Cause**: Missing TypeScript decorator metadata configuration in `tsconfig.json`.
|
|
107
|
+
|
|
108
|
+
**Solution**: **This is critical!** Ensure your `tsconfig.json` includes these two options:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"compilerOptions": {
|
|
113
|
+
"emitDecoratorMetadata": true,
|
|
114
|
+
"experimentalDecorators": true
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Why this matters**:
|
|
120
|
+
- `emitDecoratorMetadata`: Enables TypeScript to emit metadata for decorators, which is required for dependency injection to work
|
|
121
|
+
- `experimentalDecorators`: Enables decorator syntax support
|
|
122
|
+
- Without these, the DI container cannot determine parameter types and will inject `undefined`
|
|
123
|
+
|
|
124
|
+
**Check all tsconfig.json files**:
|
|
125
|
+
- Root `tsconfig.json`
|
|
126
|
+
- `examples/tsconfig.json`
|
|
127
|
+
- Any project-specific `tsconfig.json` files
|
|
128
|
+
|
|
129
|
+
**Example**:
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"extends": "../tsconfig.json",
|
|
133
|
+
"compilerOptions": {
|
|
134
|
+
"outDir": "dist",
|
|
135
|
+
"rootDir": "./",
|
|
136
|
+
"emitDecoratorMetadata": true, // ⚠️ REQUIRED
|
|
137
|
+
"experimentalDecorators": true // ⚠️ REQUIRED
|
|
138
|
+
},
|
|
139
|
+
"include": ["**/*.ts"]
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
102
143
|
### Service Not Injectable
|
|
103
144
|
|
|
104
145
|
**Error**: `Cannot resolve dependency` or service not found.
|