健康的微服务

已发行

本章内容概览:

  • Kubernetes 健康检查
  • 日志记录策略
  • 分布式追踪
  • 调试微服务
  • 容错技术

11.1 监控层次

白盒监控:

  • 应用内部的指标
  • CPU、内存、网络
  • 请求速率、延迟、错误率

黑盒监控:

  • 从外部测试系统
  • 模拟用户行为
  • 验证功能可用性

黄金信号:

  1. 延迟:请求的响应时间
  2. 流量:每秒请求数
  3. 错误:失败的请求率
  4. 饱和度:资源使用率

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
  • 结构化日志便于解析和分析
  • 分布式追踪帮助理解请求的完整路径
  • 容错技术:重试、超时、断路器、舱舱隔离、降级
  • 优雅关闭确保服务平滑退出

下一章探讨微服务的可扩展性路径。

创建于 0001/01/01 更新于 0001/01/01 1023 字 阅读约 3 分钟

提交勘误/建议