1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
| // 健康检查系统
class HealthChecker {
private services = new Map<string, ServiceHealth>();
async checkAll(): Promise<HealthReport> {
const results = await Promise.allSettled(
Array.from(this.services.values()).map(svc =>
this.checkService(svc)
)
);
const report: HealthReport = {
healthy: 0,
unhealthy: 0,
details: []
};
for (const result of results) {
if (result.status === 'fulfilled') {
report.healthy++;
report.details.push({
service: result.value.name,
status: 'healthy',
responseTime: result.value.responseTime
});
} else {
report.unhealthy++;
report.details.push({
service: result.reason.service,
status: 'unhealthy',
error: result.reason.message
});
}
}
return report;
}
private async checkService(
service: ServiceHealth
): Promise<ServiceHealth> {
const start = Date.now();
try {
// TCP检查
await this.tcpCheck(service.host, service.port);
// HTTP检查
await this.httpCheck(`${service.url}/health`);
// 响应时间
const responseTime = Date.now() - start;
if (responseTime > service.timeout) {
throw new Error('Response timeout');
}
return {
...service,
status: 'healthy',
responseTime,
lastCheck: Date.now()
};
} catch (error) {
throw {
service: service.name,
message: error.message
};
}
}
}
// 自动故障转移
class FailoverController {
private primary: string;
private secondaries: string[];
private currentPrimary: string;
async monitorAndFailover(): Promise<void> {
setInterval(async () => {
const isHealthy = await this.checkHealth(this.currentPrimary);
if (!isHealthy) {
console.warn('Primary unhealthy, initiating failover');
await this.failover();
}
}, 5000); // 每5秒检查一次
}
private async failover(): Promise<void> {
// 1. 选择新的主节点
const newPrimary = await this.selectBestSecondary();
// 2. 提升新主节点
await this.promoteToPrimary(newPrimary);
// 3. 更新DNS/负载均衡
await this.updateRouting(newPrimary);
// 4. 重新配置复制
await this.reconfigureReplication(newPrimary);
this.currentPrimary = newPrimary;
console.log(`Failover completed: ${newPrimary} is now primary`);
}
private async selectBestSecondary(): Promise<string> {
const candidates = await Promise.all(
this.secondaries.map(async (sec) => ({
id: sec,
health: await this.checkHealth(sec),
replicationLag: await this.getReplicationLag(sec)
}))
);
// 选择健康且延迟最小的
return candidates
.filter(c => c.health)
.sort((a, b) => a.replicationLag - b.replicationLag)[0].id;
}
}
|