健康的微服务
已发行
本章内容概览:
- Kubernetes 健康检查
- 日志记录策略
- 分布式追踪
- 调试微服务
- 容错技术
11.1 监控层次
白盒监控:
- 应用内部的指标
- CPU、内存、网络
- 请求速率、延迟、错误率
黑盒监控:
- 从外部测试系统
- 模拟用户行为
- 验证功能可用性
黄金信号:
- 延迟:请求的响应时间
- 流量:每秒请求数
- 错误:失败的请求率
- 饱和度:资源使用率
11.2 Kubernetes 健康检查
Liveness Probe(存活探针):
检测容器是否还在运行,失败时重启容器。
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
failureThreshold: 3
Readiness Probe(就绪探针):
检测容器是否准备好接收流量,失败时从服务中移除 Pod。
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 3
Startup Probe(启动探针):
检测容器是否启动,适用于启动时间长的应用。
startupProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 30
11.3 日志记录策略
结构化日志:
console.log(JSON.stringify({
timestamp: new Date().toISOString(),
level: 'info',
service: 'video-streaming',
message: 'Video requested',
videoId: '12345',
userId: 'user-001'
}));
日志级别:
- DEBUG:详细的调试信息
- INFO:一般信息性消息
- WARN:警告信息
- ERROR:错误信息
- FATAL:严重错误
日志聚合:
- EFK Stack (Elasticsearch + Fluentd + Kibana)
- Loki + Grafana
- CloudWatch Logs (AWS)
- Azure Monitor Logs
11.4 分布式追踪
概念:
- Trace(追踪):一个请求的完整路径
- Span(跨度):单个服务中的操作
- Trace ID:唯一标识一个追踪
- Span ID:唯一标识一个跨度
OpenTelemetry:
const { trace } = require('@opentelemetry/api');
const tracer = trace.getTracer('video-streaming');
async function streamVideo(videoId) {
const span = tracer.startSpan('streamVideo');
try {
span.setAttribute('videoId', videoId);
return video;
} finally {
span.end();
}
}
11.5 调试微服务
查看日志:
kubectl logs -f deployment/video-streaming
进入容器:
kubectl exec -it <pod-name> -- /bin/bash
端口转发:
kubectl port-forward deployment/video-streaming 3000:3000
临时调试容器:
spec:
containers:
- name: app
image: myapp:latest
- name: debug
image: nicolaka/netshoot
command: ["sleep", "3600"]
11.6 容错技术
重试(Retry):
async function callServiceWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.ok) return await response.json();
} catch (error) {
if (i === maxRetries - 1) throw error;
await sleep(Math.pow(2, i) * 1000); // 指数退避
}
}
}
超时(Timeout):
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);
try {
const response = await fetch(url, { signal: controller.signal });
return await response.json();
} finally {
clearTimeout(timeout);
}
断路器(Circuit Breaker):
防止级联失败。
class CircuitBreaker {
constructor(threshold = 5) {
this.failureCount = 0;
this.threshold = threshold;
this.state = 'CLOSED';
}
async execute(fn) {
if (this.state === 'OPEN') {
throw new Error('Circuit breaker is OPEN');
}
try {
const result = await fn();
this.onSuccess();
return result;
} catch (error) {
this.onFailure();
throw error;
}
}
}
舱舱隔离(Bulkhead):
隔离资源,防止一个服务的问题影响其他服务。
const videoStoragePool = new Pool({ max: 10 });
const uploadServicePool = new Pool({ max: 5 });
降级(Fallback):
提供备用方案。
async function getVideoInfo(videoId) {
try {
return await fetchFromCache(videoId);
} catch (error) {
return await fetchFromDatabase(videoId);
}
}
11.7 优雅关闭
处理关闭信号:
const server = app.listen(PORT);
process.on('SIGTERM', () => {
console.log('SIGTERM signal received: closing HTTP server');
server.close(() => {
console.log('HTTP server closed');
});
});
总结
- 监控是确保微服务健康运行的关键
- 黄金信号:延迟、流量、错误、饱和度
- Kubernetes 提供三种探针:liveness、readiness、startup
- 结构化日志便于解析和分析
- 分布式追踪帮助理解请求的完整路径
- 容错技术:重试、超时、断路器、舱舱隔离、降级
- 优雅关闭确保服务平滑退出
下一章探讨微服务的可扩展性路径。