云原生微服务踩坑记:187个服务降到23个,故障率降低90%

云原生微服务踩坑记:187个服务降到23个,故障率降低90%

作者按: 去年双11前,我们的微服务系统有187个服务,故障率居高不下。经过半年重构,降到23个核心服务,故障率降低90%。本文是真实复盘,包含完整代码和血泪教训。阅读约25分钟。


引言:我们怎么把微服务玩坏的?

去年双11前,我们做了一个"艰难的决定":把运行了5年的单体应用拆成微服务。

初衷很美好:

  • 团队独立开发部署,提升效率
  • 故障隔离,一个服务挂了不影响全局
  • 技术栈灵活,不同服务可以用不同语言

现实很骨感:

  • 分布式链路追踪缺失,排查问题靠"猜"
  • 服务雪崩,一个慢查询拖垮整个系统
  • 配置管理混乱,改个开关要发版
  • 版本依赖复杂,升级一个服务导致连锁反应

最惨的时候,我们有187个微服务,运维成本巨大,故障率反而比单体应用高。

经过半年的踩坑和实践,我们重构为23个核心服务,故障率降低90%。本文将毫无保留地分享这个过程。

技术栈: Spring Cloud Alibaba + Nacos + Sentinel + SkyWalking + Kubernetes


一、微服务架构设计原则

1.1 服务拆分策略

错误的拆分方式(我们踩过的坑):

按技术层拆分:UserController、UserService、UserDAO各成一个服务

  • 问题:每次需求变更要改3个服务,发布顺序还要考虑依赖

拆得太细:一个只有2个接口的服务也单独部署

  • 问题:服务数量爆炸(我们最多时有187个微服务),运维成本巨大

数据库共享:所有服务连同一个数据库

  • 问题:一个服务的慢SQL会影响其他服务,完全没有隔离性

正确的拆分原则(DDD领域驱动设计):

按业务边界拆分:订单服务、商品服务、用户服务、支付服务...

  • 好处:每个服务职责清晰,团队自治

数据库独享:每个服务有自己的数据库

  • 好处:故障隔离,可以针对业务特点选择数据库(订单用MySQL,搜索用ElasticSearch)

前后端分离 + BFF层

复制代码
┌─────────────────────────────────────┐
│         前端(Web/App)              │
└──────────────┬──────────────────────┘
               ↓
┌─────────────────────────────────────┐
│    BFF层(Backend For Frontend)    │
│  - 聚合多个微服务的数据              │
│  - 适配前端的数据格式                │
│  - 处理鉴权、限流等横切逻辑         │
└──────────────┬──────────────────────┘
               ↓
┌─────────────────────────────────────┐
│         微服务层                     │
│  订单服务 | 商品服务 | 用户服务 ...  │
└─────────────────────────────────────┘

实战案例:电商平台的微服务拆分

服务名 职责 数据库 接口数量 QPS
用户服务 注册、登录、用户信息管理 MySQL 15 5000
商品服务 商品CRUD、库存管理 MySQL + Redis 23 8000
订单服务 下单、订单查询、订单取消 MySQL + Redis 18 3000
支付服务 支付、退款、对账 MySQL 12 1000
搜索服务 商品搜索、推荐 Elasticsearch 8 10000
通知服务 短信、邮件、App推送 MongoDB 6 2000

拆分后的好处:

  • 订单服务压力大?单独扩容订单服务的Pod(K8s)
  • 搜索服务要升级ES版本?不影响其他服务
  • 新同事入职?只需了解他负责的服务,不用掌握整个系统

1.2 服务通信方式选择

微服务之间如何通信?我们有3种方式:

通信方式 适用场景 优点 缺点
REST API 同步调用,需要立即返回结果 简单直观,调试方便 耦合性强,性能一般
RPC(Dubbo/gRPC) 高性能同步调用 性能高(二进制传输),有服务发现 学习成本,调试不如HTTP直观
消息队列(Kafka/RocketMQ) 异步调用,不需要立即返回 解耦,削峰填谷,失败可重试 复杂性高,需要保证消息不丢失

我们的实践:

复制代码
┌─────────────┐
│  下单请求    │
└──────┬──────┘
       ↓
┌──────────────────────────────────────┐
│         订单服务(主流程)            │
│  1. 创建订单(REST API,同步)       │
│     → 调用商品服务扣减库存            │
│     → 调用支付服务预扣款              │
│  2. 发送消息(异步)                 │
│     → 通知物流服务发货                │
│     → 通知通知服务发送确认短信         │
│     → 通知大数据平台记录订单数据       │
└──────────────────────────────────────┘

关键原则:

  1. 核心流程用同步(下单必须立即知道成功还是失败)
  2. 边缘业务用异步(物流服务慢一点没关系,消息队列削峰)
  3. 禁止使用循环调用(A→B→C→A,会形成死循环)

二、服务治理核心组件

2.1 服务注册与发现(Nacos)

问题: 微服务实例是动态变化的(扩容、缩容、实例崩溃),调用方怎么知道有哪些实例可用?

解决方案: 服务注册与发现

java 复制代码
// 1. 服务启动时报到Nacos
@SpringBootApplication
@EnableDiscoveryClient  // 启用服务发现
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// 2. 配置文件(application.yml)
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.100:8848  # Nacos服务器地址
        namespace: dev  # 命名空间(隔离开发/测试/生产)
        group: ECOMMERCE  # 分组(同一分组下的服务才能互相发现)
      config:
        server-addr: 192.168.1.100:8848
        file-extension: yaml  # 配置格式

// 3. 调用其他服务(通过服务名,不用写死IP)
@RestController
public class OrderController {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/order/{userId}")
    public Order getOrder(@PathVariable Long userId) {
        // 不用写 http://192.168.1.101:8080/user/...
        // 直接写服务名,Nacos会自动做负载均衡
        User user = restTemplate.getForObject(
            "http://user-service/user/" + userId, 
            User.class
        );
        // ...
    }
}

Nacos的高级特性:

  1. 健康检查:Nacos定期ping服务实例,不健康的实例会被摘除
  2. 自我保护机制:网络分区时,不会盲目摘除实例(避免"雪崩")
  3. 配置中心:不用重启服务就能改配置(如开关某个功能)
yaml 复制代码
# Nacos配置中心示例
# 在Nacos控制台添加配置:order-service.yaml

# 功能开关
feature:
  coupon: true  # 优惠券功能
  flash_sale: false  # 秒杀功能(默认关闭)

# 限流配置
ratelimit:
  qps: 1000  # 每秒最多1000次请求

# 在代码中动态获取配置
@RefreshScope  // 配置变更时自动刷新
@RestController
public class OrderController {
    
    @Value("${feature.coupon}")
    private boolean couponEnabled;
    
    @PostMapping("/order")
    public Response createOrder(@RequestBody OrderRequest req) {
        if (couponEnabled) {
            // 使用优惠券逻辑
        }
        // ...
    }
}

2.2 服务容错(Sentinel)

问题: 一个服务响应慢,会导致调用方线程池耗尽,进而引发雪崩。

场景还原:

复制代码
用户请求 → 订单服务 → 支付服务(响应慢,5秒才返回)
                      → 线程池耗尽(默认200个线程)
                      → 新请求进不来
                      → 订单服务也挂了
                      → 所有依赖订单服务的服务都挂了
                      → 整个系统崩溃

解决方案: 限流、熔断、降级(Sentinel)

java 复制代码
// 1. 引入Sentinel依赖
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

// 2. 配置Sentinel控制台地址
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 192.168.1.101:8080  # Sentinel控制台
      port: 8719  # 与控制台通信的端口

// 3. 定义资源(需要保护的方法)
@Service
public class OrderService {
    
    // 方式1:注解方式(推荐)
    @SentinelResource(value = "createOrder", 
                      blockHandler = "createOrderBlockHandler",  // 被限流/熔断时的处理方法
                      fallback = "createOrderFallback")  // 抛出异常时的处理方法
    public Order createOrder(OrderRequest req) {
        // 正常业务逻辑
        // 调用支付服务
        Payment payment = paymentService.pay(req);
        // ...
        return order;
    }
    
    // 被限流/熔断时走这里
    public Order createOrderBlockHandler(OrderRequest req, BlockException ex) {
        // 返回降级结果(如:提示用户"系统繁忙,请稍后重试")
        return Order.builder()
                   .status("FAILED")
                   .message("系统繁忙,请稍后重试")
                   .build();
    }
    
    // 抛出异常时走这里
    public Order createOrderFallback(OrderRequest req, Throwable t) {
        // 记录日志,返回默认结果
        log.error("创建订单失败", t);
        return Order.builder()
                   .status("ERROR")
                   .message("创建订单失败,请联系客服")
                   .build();
    }
}

// 4. 在Sentinel控制台配置规则(也可以代码配置)
/**
 * 限流规则:
 * - QPS > 1000 时,新的请求直接拒绝(快速失败)
 * 
 * 熔断规则:
 * - 响应时间 > 2000ms 的请求占比 > 50% 时,熔断10秒
 * - 熔断期间,所有请求直接走降级方法
 */

Sentinel的三种保护机制:

机制 作用 配置示例
限流(Flow Control) 控制QPS,防止系统被冲垮 QPS > 1000时拒绝请求
熔断(Circuit Breaking) 调用慢/异常多时,暂时切断调用 错误率 > 50% 时熔断10秒
降级(Fallback) 调用失败时,返回默认结果 抛出异常时返回"系统维护中"

实战经验:

  1. 核心接口必须配置限流(如下单、支付),防止恶意攻击或流量突增
  2. 调用第三方服务必须配置熔断(如支付、短信),第三方不可控
  3. 降级方法要友好(不要直接抛异常给用户),可以返回缓存数据或默认结果

2.3 分布式链路追踪(SkyWalking)

问题: 一个请求经过十几个服务,怎么快速定位哪个服务慢?

解决方案: 分布式链路追踪(SkyWalking)

复制代码
请求流程:
用户请求 → API网关 → 订单服务 → 商品服务 → 库存服务 → 数据库
                   → 支付服务 → 第三方支付平台
                   → 通知服务 → 短信平台
                   
问题:用户说"下单慢",到底是哪里慢?

SkyWalking的实现原理:

  1. 每个请求分配一个Trace ID(如:trace-12345)
  2. 每个服务调用是一个Span(如:span-1=订单服务,span-2=商品服务)
  3. Span之间有父子关系(span-2的parent是span-1)
  4. 记录每个Span的开始时间、结束时间、状态码
java 复制代码
// 1. 引入SkyWalking依赖
<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-trace</artifactId>
    <version>8.16.0</version>
</dependency>

// 2. 配置agent(启动时加JVM参数)
// java -javaagent:/path/to/skywalking-agent.jar -Dskywalking.agent.service_name=order-service -Dskywalking.collector.backend_service=192.168.1.102:11800 -jar order-service.jar

// 3. 在代码中获取Trace ID(方便日志关联)
@RestController
public class OrderController {
    
    @GetMapping("/order/{orderId}")
    public Order getOrder(@PathVariable String orderId) {
        // 获取当前Trace ID
        String traceId = TraceContext.traceId();
        log.info("TraceId={}, 查询订单, orderId={}", traceId, orderId);
        
        Order order = orderService.getOrder(orderId);
        
        log.info("TraceId={}, 查询订单成功", traceId);
        return order;
    }
}

// 4. 自定义Span(追踪某个方法)
@Service
public class OrderService {
    
    @Trace(operationName = "createOrder")  // 自定义Span
    public Order createOrder(OrderRequest req) {
        // 这个方法会在SkyWalking中显示为一个Span
        // 可以看到执行时间、是否成功等信息
        // ...
    }
}

SkyWalking UI界面功能:

  1. 拓扑图:展示服务之间的调用关系(哪些服务调用了哪些服务)
  2. Trace查询:输入Trace ID,查看完整调用链(哪个服务慢一目了然)
  3. 性能剖析:找出慢方法(如:OrderService.createOrder占用500ms)
  4. 告警:响应时间 > 2秒,自动发邮件/短信通知

实战案例:

复制代码
问题:用户投诉"下单要5秒,太慢了"

排查过程:
1. 在SkyWalking中搜索 trace(根据订单号或用户ID)
2. 发现调用链:
   - API网关:50ms
   - 订单服务:200ms
   - 支付服务:3500ms  ← 慢在这里!
   - 通知服务:100ms
3. 查看支付服务的日志,发现是调用第三方支付平台超时(设置了3秒超时)
4. 优化方案:
   - 支付改成异步(下完单再慢慢扣款)
   - 或者设置支付服务的熔断(第三方超时就降级)

三、配置管理与环境变量

3.1 配置中心(Nacos)

问题: 改一个配置(如:关闭某个功能),要重新打包、发布、重启服务?

解决方案: 配置中心(Nacos/Apollo)

java 复制代码
// 传统方式(要改代码、重新打包)
@Component
public class OrderService {
    private boolean couponEnabled = true;  // 写死在代码里
    
    public void createOrder() {
        if (couponEnabled) {  // 要关闭?改代码,重新发布
            // ...
        }
    }
}

// 配置中心方式(动态刷新,不用重启)
// 在Nacos中配置 order-service.properties

coupon.enabled=true
flash.sale.enabled=false
ratelimit.qps=1000

// 代码中读取
@RestController
@RefreshScope  // 配置变更时自动刷新
public class OrderController {
    
    @Value("${coupon.enabled}")
    private boolean couponEnabled;
    
    @PostMapping("/order")
    public Response createOrder(@RequestBody OrderRequest req) {
        if (couponEnabled) {
            // 使用优惠券
        }
        // ...
    }
}

配置中心的好处:

  1. 动态刷新:改配置不用重启服务(秒级生效)
  2. 版本管理:配置也有版本,可以回滚
  3. 权限控制:谁改了配置?有审计日志
  4. 灰度发布:1%的服务器用新配置,验证OK再全量

3.2 环境变量与K8s ConfigMap

问题: 开发、测试、生产环境配置不一样,怎么管理?

解决方案: 环境变量 + Kubernetes ConfigMap/Secret

yaml 复制代码
# 1. 在K8s中定义ConfigMap(配置文件)
apiVersion: v1
kind: ConfigMap
metadata:
  name: order-service-config
  namespace: production
data:
  application.yaml: |
    spring:
      datasource:
        url: jdbc:mysql://mysql-production:3306/order_db
        username: ${MYSQL_USER}  # 从环境变量读取
        password: ${MYSQL_PASSWORD}
      redis:
        host: ${REDIS_HOST}
        port: 6379
    
    # 功能开关
    feature:
      coupon: true
      flash_sale: false

---
# 2. 在K8s中定义Secret(敏感信息)
apiVersion: v1
kind: Secret
metadata:
  name: order-service-secret
  namespace: production
type: Opaque
data:
  mysql-user: bXlzcWw=  # base64编码的"mysql"
  mysql-password: cGFzc3dvcmQxMjM=  # base64编码的"password123"

---
# 3. 在Deployment中引用
apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: order-service
        image: order-service:latest
        ports:
        - containerPort: 8080
        env:
        - name: MYSQL_USER
          valueFrom:
            secretKeyRef:
              name: order-service-secret
              key: mysql-user
        - name: MYSQL_PASSWORD
          valueFrom:
            secretKeyRef:
              name: order-service-secret
              key: mysql-password
        - name: REDIS_HOST
          value: "redis-production"
        volumeMounts:
        - name: config-volume
          mountPath: /config
      volumes:
      - name: config-volume
        configMap:
          name: order-service-config

最佳实践:

  1. 敏感信息用Secret(密码、API Key),不要写在代码里
  2. 环境差异用ConfigMap,不用改代码就能切换环境
  3. 配置加密(如:数据库密码加密存储),防止泄露

四、监控告警体系

4.1 监控指标(Prometheus + Grafana)

需要监控什么?

类别 指标 告警阈值 工具
业务指标 订单量、支付成功率、注册人数 订单量同比下跌 > 30% 自定义埋点 + Prometheus
性能指标 QPS、响应时间、错误率 P99响应时间 > 2秒 SkyWalking + Prometheus
资源指标 CPU、内存、磁盘、网络 CPU > 80% 持续5分钟 Node Exporter + Prometheus
JVM指标 堆内存、GC次数、线程数 堆内存使用率 > 90% JMX Exporter + Prometheus

Prometheus配置示例:

yaml 复制代码
# prometheus.yml
global:
  scrape_interval: 15s  # 每15秒采集一次

scrape_configs:
  # 采集订单服务的指标
  - job_name: 'order-service'
    metrics_path: '/actuator/prometheus'
    static_configs:
      - targets: ['order-service:8080']
  
  # 采集K8s节点的指标
  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

# 在Spring Boot中暴露指标
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: prometheus,health,info
  metrics:
    export:
      prometheus:
        enabled: true

Grafana仪表盘示例:

复制代码
┌─────────────────────────────────────────────────┐
│           订单服务监控仪表盘                     │
├─────────────────────────────────────────────────┤
│ [面板1] QPS(每秒请求数)                        │
│   - 当前值:500 QPS                             │
│   - 图表:折线图(最近1小时)                    │
│                                                 │
│ [面板2] 响应时间(P50/P99)                     │
│   - P50:200ms                                  │
│   - P99:1500ms                                 │
│   - 图表:折线图                                │
│                                                 │
│ [面板3] 错误率                                  │
│   - 当前值:0.5%                                │
│   - 告警线:> 1% 触发告警                      │
│                                                 │
│ [面板4] JVM堆内存使用率                          │
│   - 当前值:65%                                 │
│   - 告警线:> 90% 触发告警                     │
└─────────────────────────────────────────────────┘

4.2 告警规则(AlertManager)

yaml 复制代码
# alertmanager.yml
route:
  group_by: ['alertname', 'service']
  group_wait: 10s  # 等待10秒,看看还有没有其他告警
  group_interval: 10s  # 发送告警的间隔
  repeat_interval: 1h  # 重复告警的间隔
  receiver: 'webhook'  # 接收者

receivers:
- name: 'webhook'
  webhook_configs:
  - url: 'http://alert-handler:8080/alert'  # 自定义的告警处理服务
    send_resolved: true  # 问题恢复时也发送通知

# 在Prometheus中定义告警规则
# prometheus.rules.yml
groups:
- name: order-service-alerts
  rules:
  # 规则1:订单服务不可达
  - alert: OrderServiceDown
    expr: up{job="order-service"} == 0
    for: 1m  # 持续1分钟才告警(防止误报)
    labels:
      severity: critical
    annotations:
      summary: "订单服务不可达"
      description: "订单服务 {{ $labels.instance }} 已经下线超过1分钟"
  
  # 规则2:响应时间过长
  - alert: HighResponseTime
    expr: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{job="order-service"}[5m])) > 2
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "订单服务响应时间过长"
      description: "P99响应时间为 {{ $value }} 秒,超过阈值2秒"
  
  # 规则3:错误率过高
  - alert: HighErrorRate
    expr: rate(http_requests_total{job="order-service",status=~"5.."}[5m]) / rate(http_requests_total{job="order-service"}[5m]) > 0.01
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "订单服务错误率过高"
      description: "错误率为 {{ $value | humanizePercentage }},超过阈值1%"

告警通知方式:

  1. 紧急(Critical):打电话 + 发短信 + 钉钉群@所有人
  2. 警告(Warning):钉钉群通知 + 邮件
  3. 信息(Info):只记录日志,不通知

五、故障恢复与混沌工程

5.1 常见故障与恢复策略

故障类型 原因 恢复策略 自动化程度
服务崩溃 OOM、代码bug、依赖服务不可用 K8s自动重启Pod ✅ 全自动
数据库慢查询 索引缺失、数据量过大 DBA优化SQL + 限流 ⚠️ 半自动(需要DBA介入)
网络分区 机房故障、网络设备故障 流量切换到其他机房 ✅ 全自动(多机房部署)
配置错误 人为误操作 回滚配置(Nacos/Apollo支持) ✅ 全自动
依赖服务不可用 第三方服务挂了 熔断 + 降级(返回缓存数据) ✅ 全自动

K8s的自动恢复机制:

yaml 复制代码
# 1. 健康检查(Liveness Probe)
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: order-service
        livenessProbe:  # 存活探针(检查服务是否还活着)
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60  # 启动后60秒才开始检查
          periodSeconds: 10  # 每10秒检查一次
          failureThreshold: 3  # 连续失败3次,重启Pod
        
        readinessProbe:  # 就绪探针(检查服务是否准备好接收流量)
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 5
          failureThreshold: 3  # 连续失败3次,从负载均衡中摘除
        
        # 2. 资源限制(防止OOM)
        resources:
          requests:  # 调度时保证有这么多资源
            memory: "512Mi"
            cpu: "500m"
          limits:  # 最多使用这么多资源
            memory: "1Gi"
            cpu: "1000m"
        
        # 3. 优雅关闭(SIGTERM信号)
        lifecycle:
          preStop:  # 收到SIGTERM后,先执行这个,再杀进程
            exec:
              command: ["sh", "-c", "sleep 30"]  # 等待30秒,让请求处理完
        
# 4. 自动扩缩容(HPA)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 3  # 最少3个Pod
  maxReplicas: 10  # 最多10个Pod
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70  # CPU使用率 > 70% 时扩容

5.2 混沌工程(ChaosBlade)

问题: 系统看起来很稳定,但真出故障时能不能快速恢复?

解决方案: 混沌工程(主动注入故障,验证系统的容错能力)

bash 复制代码
# 1. 安装ChaosBlade
wget https://github.com/chaosblade-io/chaosblade/releases/download/v1.7.0/chaosblade-1.7.0-linux-amd64.tar.gz
tar -xzf chaosblade-1.7.0-linux-amd64.tar.gz

# 2. 实验1:杀掉订单服务的Pod(验证K8s能否自动重启)
./blade create k8s pod-pod restart --namespace production --labels "app=order-service" --count 1

# 观察:
# - K8s是否在1分钟内重启Pod?
# - 重启期间,请求是否有失败?
# - 重启后,服务是否正常?

# 3. 实验2:模拟网络延迟(验证超时配置是否合理)
./blade create network delay --time 3000 --interface eth0 --timeout 60

# 观察:
# - 调用这个服务的客户端是否会超时?
# - 超时后是否有降级逻辑?
# - 会不会导致线程池耗尽?

# 4. 实验3:模拟CPU满载(验证限流是否生效)
./blade create cpu fullload --timeout 60

# 观察:
# - CPU > 80% 时,限流是否生效?
# - 新请求是否被拒绝(返回429 Too Many Requests)?
# - 还是继续处理,导致服务崩溃?

# 5. 实验4:模拟数据库慢查询(验证熔断是否生效)
./blade create mysql delay --time 5000 --database order_db --timeout 60

# 观察:
# - 慢查询占比 > 50% 时,Sentinel是否会熔断?
# - 熔断期间,请求是否走降级逻辑?

混沌工程的实施步骤:

  1. 成立混沌工程小组(开发、测试、运维、SRE)
  2. 制定实验计划(哪些故障要模拟?预期结果是什么?)
  3. 在生产环境小规模实验(先用1%的流量,验证OK再扩大)
  4. 记录实验结果(发现了哪些问题?如何修复?)
  5. 定期演练(每季度一次,保证系统始终健壮)

六、总结与最佳实践

6.1 微服务治理 checklist

✅ 服务拆分

  • 按业务边界拆分(DDD),不要按技术层拆分
  • 数据库独享,不要共享数据库
  • 服务数量控制在合理范围(建议 < 50个)

✅ 服务通信

  • 核心流程用同步调用(REST/RPC)
  • 边缘业务用异步调用(消息队列)
  • 配置超时、重试、熔断(防止雪崩)

✅ 服务治理

  • 服务注册与发现(Nacos/Eureka)
  • 配置中心(Nacos/Apollo)
  • 限流、熔断、降级(Sentinel/Resilience4j)
  • 分布式链路追踪(SkyWalking/Zipkin)

✅ 监控告警

  • 监控业务指标(订单量、支付成功率)
  • 监控性能指标(QPS、响应时间、错误率)
  • 监控资源指标(CPU、内存、磁盘)
  • 配置合理的告警阈值(避免告警风暴)

✅ 故障恢复

  • K8s健康检查(Liveness/Readiness Probe)
  • 资源限制(防止OOM)
  • 优雅关闭(SIGTERM)
  • 自动扩缩容(HPA)
  • 定期混沌工程演练

6.2 踩坑经验总结

坑1:服务拆分得太细

  • 现象:一个简单需求要改5个服务
  • 原因:没有考虑团队规模(小团队不适合太多微服务)
  • 解决方案:合并低频变化的服务(如:通知服务+日志服务 → 基础设施服务)

坑2:分布式事务难题

  • 现象:下单成功后,扣库存失败,数据不一致
  • 原因:跨服务的事务很难保证ACID
  • 解决方案:用最终一致性( Seata/消息队列+补偿机制),不要强一致性

坑3:版本依赖地狱

  • 现象:升级一个基础服务,导致所有依赖它的服务都要升级
  • 原因:没有做接口版本管理
  • 解决方案:接口加版本号(/api/v1/order),新老版本共存,逐步迁移

坑4:测试环境不稳定

  • 现象:测试环境经常挂,影响开发进度
  • 原因:测试环境和生产环境差异大(配置、数据、依赖服务)
  • 解决方案:用Docker ComposeK8s Namespace搭建隔离的测试环境

参考资料

  1. Spring Cloud Alibaba官方文档
  2. Sentinel官方文档
  3. SkyWalking官方文档
  4. Kubernetes官方文档
  5. 《微服务架构设计模式》 - Chris Richardson 著

如果本文帮你少踩了坑,请点赞 + 收藏 + 关注三连!

讨论题:

  1. 你们公司的微服务是怎么拆分的?遇到过哪些坑?
  2. 你觉得微服务数量多少合适?我们最终定了23个核心服务
  3. 有没有比Nacos更好的服务注册与发现方案推荐?

期待你的分享和讨论!

相关推荐
郑寿昌1 小时前
AI原生存储架构:存算智一体革命
架构·ai-native
2601_957786771 小时前
星链引擎矩阵系统:流批一体湖仓架构与亿级数据实时数仓技术实践
大数据·矩阵·架构
珂玥c1 小时前
k8s集群切换master
云原生·容器·kubernetes
zandy10112 小时前
HENGSHI SENSE加速引擎架构深度解析:MPP列存与ClickHouse物化视图实战
clickhouse·架构·企业级bi·mpp列存
LT10157974442 小时前
2026年微服务性能测试平台选型指南:分布式架构适配与服务联动测试
分布式·微服务·架构
若兰幽竹2 小时前
【HarmonyOS 6.1 全场景实战】《灵犀厨房》实战之补充【架构进化】灵犀厨房四层分层设计:给鸿蒙 App 搭一副坚不可摧的骨架
架构·鸿蒙系统·harmonyos6.1.0·灵犀厨房
颯沓如流星2 小时前
ZKube:优雅易用的 ZooKeeper 可视化管理工具
分布式·zookeeper·云原生
fuquxiaoguang2 小时前
架构模式革新:用“旁路镜像”改造老旧系统——中间件驱动的渐进式AI落地范式
人工智能·中间件·架构
AI科技星3 小时前
算法联盟·全域数学公理体系下黑洞标量毛发与LVK引力波O4全维理论、求导、证明、计算、验证、分析
人工智能·线性代数·算法·架构·学习方法·量子计算