知识模块
☕ Java 知识模块
十五、Java 架构师
高可用、高并发、微服务架构

高可用、高并发、微服务架构

面试高频考点:SLA 可用性指标、容灾架构设计、限流降级熔断、负载均衡策略、分布式缓存、消息队列削峰、微服务拆分原则、服务注册发现、分布式事务、分布式链路追踪、云原生架构

一、高可用设计

什么是高可用?

高可用(High Availability)是指系统在面临各种故障时,仍能持续提供服务的能力。通常用 SLA(Service Level Agreement)来衡量。

可用性指标(SLA)

SLA 等级可用性年停机时间适用场景
2 个 999%87.6 小时一般系统
3 个 999.9%8.76 小时商业系统
4 个 999.99%52.6 分钟金融/支付
5 个 999.999%5.26 分钟核心交易
可用性计算公式:
可用性 = (总时间 - 停机时间) / 总时间 × 100%

示例:99.99% 可用性
年停机时间 = 365 × 24 × 60 × (1 - 0.9999) = 52.6 分钟

容灾架构设计

同城双活

                    ┌─────────────────┐
                    │   负载均衡器     │
                    │   (主/备切换)    │
                    └────────┬────────┘

              ┌──────────────┼──────────────┐
              ▼              ▼              ▼
        ┌──────────┐   ┌──────────┐   ┌──────────┐
        │  机房 A   │   │  机房 B   │   │  机房 C   │
        │ (同城双活) │   │ (同城双活) │   │ (异地灾备) │
        └────┬─────┘   └────┬─────┘   └────┬─────┘
             │              │              │
             └──────────────┼──────────────┘

                    ┌───────────────┐
                    │   数据同步     │
                    │ (主从复制/双写) │
                    └───────────────┘

同城双活特点

  • 两个机房距离 < 50km,网络延迟 < 2ms
  • 两机房同时对外提供服务
  • 单机房故障,流量自动切换
  • 数据实时同步,一致性较高

异地多活

                    ┌─────────────────┐
                    │   全局负载均衡   │
                    │      (GSLB)     │
                    └────────┬────────┘

        ┌────────────────────┼────────────────────┐
        ▼                    ▼                    ▼
  ┌──────────┐        ┌──────────┐        ┌──────────┐
  │ 北京机房  │        │ 上海机房  │        │ 广州机房  │
  │ (完整服务) │        │ (完整服务) │        │ (完整服务) │
  └────┬─────┘        └────┬─────┘        └────┬─────┘
       │                   │                   │
       └───────────────────┼───────────────────┘

                   ┌───────────────┐
                   │  异步数据同步  │
                   │ (消息队列/ Binlog)│
                   └───────────────┘

异地多活特点

  • 机房分布在不同城市,距离 > 100km
  • 每个机房独立部署完整服务
  • 用户就近访问,延迟低
  • 数据异步同步,可能有延迟
  • 真正的灾难级容灾能力

故障转移与恢复

健康检查机制

# Nacos 健康检查配置
spring:
  cloud:
    nacos:
      discovery:
        heart-beat-interval: 5000    # 心跳间隔 5s
        heart-beat-timeout: 15000    # 心跳超时 15s
        ip-delete-timeout: 30000     # 实例删除超时 30s
// 自定义健康检查
@Component
public class CustomHealthIndicator implements HealthIndicator {
    
    @Override
    public Health health() {
        // 检查数据库连接
        if (!checkDatabase()) {
            return Health.down()
                .withDetail("database", "unavailable")
                .build();
        }
        // 检查 Redis 连接
        if (!checkRedis()) {
            return Health.down()
                .withDetail("redis", "unavailable")
                .build();
        }
        return Health.up().build();
    }
}

故障转移策略

故障转移流程:
1. 健康检查失败 → 标记实例为不可用
2. 负载均衡器剔除故障实例
3. 新请求路由到健康实例
4. 故障实例恢复后自动注册

故障转移策略:
- Failover:自动切换到备用服务
- Failfast:快速失败,抛出异常
- Failsafe:忽略异常,返回默认值
- Failback:自动恢复

限流降级熔断

限流(Rate Limiting)

// Sentinel 限流规则
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("getUserInfo");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);  // QPS 限制为 100
rules.add(rule);
FlowRuleManager.loadRules(rules);
 
// 注解方式限流
@SentinelResource(value = "getUserInfo", blockHandler = "handleBlock")
public UserInfo getUserInfo(Long userId) {
    return userService.getById(userId);
}
 
// 限流回调方法
public UserInfo handleBlock(Long userId, BlockException ex) {
    return UserInfo.getDefault();  // 返回默认值
}

限流算法

算法原理优点缺点
固定窗口固定时间窗口计数简单边界突发流量
滑动窗口窗口滑动计数平滑内存占用高
令牌桶恒定速率放令牌允许突发实现复杂
漏桶恒定速率流出削峰填谷不能突发
令牌桶算法:
┌─────────────┐
│ 令牌生成器   │ ──→ 恒定速率放令牌
└──────┬──────┘

┌─────────────┐     桶满丢弃
│   令牌桶    │ ←──────────────┐
│  (容量 N)   │                │
└──────┬──────┘                │
       │                       │
       ▼                       │
┌─────────────┐                │
│   请求处理   │ ──→ 获取令牌成功 ──┘
└──────┬──────┘
       │ 无令牌

   请求被限流

熔断(Circuit Breaker)

// Sentinel 熔断规则
DegradeRule degradeRule = new DegradeRule("getUserInfo");
degradeRule.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType());
degradeRule.setCount(0.5);     // 错误比例 50%
degradeRule.setTimeWindow(10); // 熔断时长 10s
degradeRule.setMinRequestAmount(10);  // 最小请求数
DegradeRuleManager.loadRules(Collections.singletonList(degradeRule));

熔断器状态机

           失败率 >= 阈值
    ┌─────────────────────────┐
    │                         ▼
┌────────┐  半开状态成功  ┌────────┐
│  关闭  │ ←───────────── │  半开  │
│ (Closed)│              │ (Half-Open)│
└────┬───┘               └────┬───┘
     │                        │
     │   失败率 < 阈值         │ 半开状态失败
     │   (正常请求)            │
     │                        ▼
     │                   ┌────────┐
     └───────────────────│  打开  │
                         │ (Open) │
                         └────────┘

                             │ 熔断时间到
                             └────────┐

                                   进入半开

降级(Degradation)

// 降级策略
@Service
public class ProductService {
    
    @SentinelResource(
        value = "getProductDetail",
        fallback = "getProductDetailFallback",  // 降级方法
        blockHandler = "handleBlock"            // 限流熔断处理
    )
    public ProductDetail getProductDetail(Long productId) {
        // 查询商品详情(包含库存、价格等实时数据)
        return productClient.getDetail(productId);
    }
    
    // 降级方法:返回简化数据
    public ProductDetail getProductDetailFallback(Long productId, Throwable ex) {
        ProductDetail detail = new ProductDetail();
        detail.setId(productId);
        detail.setName("商品暂不可用");
        // 从本地缓存获取基础信息
        detail.setPrice(localCache.getBasicPrice(productId));
        return detail;
    }
}

降级策略分类

策略说明适用场景
自动降级超时/失败率触发下游服务故障
手动降级配置中心开关大促/高峰期
读降级读缓存/默认值数据一致性要求低
写降级异步写入/延迟写入写操作非核心

灰度发布与回滚

灰度发布流程

灰度发布流程:
1. 新版本部署到灰度服务器
2. 路由规则配置灰度流量比例
3. 监控灰度服务指标
4. 逐步增加灰度流量
5. 全量发布或回滚

┌──────────────────────────────────────────────────┐
│                    负载均衡器                      │
└────────────────────────┬─────────────────────────┘

         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   ┌──────────┐    ┌──────────┐    ┌──────────┐
   │ 旧版本 v1 │    │ 旧版本 v1 │    │ 新版本 v2 │
   │  (40%)   │    │  (40%)   │    │  (20%)   │  ← 灰度
   └──────────┘    └──────────┘    └──────────┘
# Nacos 灰度配置
spring:
  cloud:
    nacos:
      discovery:
        metadata:
          version: v2  # 版本标识
          weight: 20   # 权重(灰度流量比例)

金丝雀发布 vs 蓝绿部署

对比项金丝雀发布蓝绿部署
资源占用少(逐步替换)多(双倍资源)
回滚速度较慢快(切换流量)
风险低(小流量验证)中(全量切换)
适用场景大规模服务小规模/关键服务
蓝绿部署架构:
┌──────────────────────────────────────┐
│            负载均衡器/网关             │
└──────────────────┬───────────────────┘

         ┌─────────┴─────────┐
         ▼                   ▼
   ┌──────────┐        ┌──────────┐
   │ 蓝环境   │        │ 绿环境   │
   │ (v1 生产) │        │ (v2 预发) │
   │ 活跃 ✓   │        │ 待命     │
   └──────────┘        └──────────┘
        
发布时:切换流量到绿环境,蓝环境保留便于回滚

二、高并发架构

并发指标

指标全称含义示例
QPSQueries Per Second每秒查询数10000 QPS
TPSTransactions Per Second每秒事务数5000 TPS
RTResponse Time响应时间50ms
并发数Concurrent Users同时在线用户10000
关键公式:
QPS = 并发数 / 平均响应时间
并发数 = QPS × 平均响应时间

示例:
- 平均响应时间 100ms
- QPS 目标 10000
- 需要并发数 = 10000 × 0.1 = 1000

负载均衡策略

负载均衡算法

算法原理优点缺点适用场景
轮询依次分配简单公平不考虑性能服务器性能相近
加权轮询按权重分配考虑性能差异不考虑负载服务器性能不同
最少连接连接数最少优先动态负载均衡需维护连接数长连接场景
IP Hash按 IP 分配会话保持分配不均有状态服务
一致性 Hash按 Hash 环分配扩缩容影响小实现复杂缓存场景
随机随机分配简单分配不均无状态服务
一致性 Hash 算法:
          服务器 A


服务器 D ◄───┼───► 服务器 B


          服务器 C

请求路由:Hash(请求 key) → 顺时针找到第一个服务器
扩缩容:只影响相邻节点,不影响全局

负载均衡实现

# Nginx 负载均衡配置
upstream backend {
    # 加权轮询
    server 192.168.1.1:8080 weight=3;
    server 192.168.1.2:8080 weight=2;
    server 192.168.1.3:8080 weight=1;
    
    # 健康检查
    server 192.168.1.4:8080 backup;  # 备用服务器
    server 192.168.1.5:8080 down;    # 下线服务器
}
 
# IP Hash
upstream backend_iphash {
    ip_hash;
    server 192.168.1.1:8080;
    server 192.168.1.2:8080;
}
 
# 最少连接
upstream backend_least_conn {
    least_conn;
    server 192.168.1.1:8080;
    server 192.168.1.2:8080;
}

分布式缓存架构

缓存架构模式

单机缓存架构:
┌─────────┐    ┌─────────┐    ┌─────────┐
│  应用   │ ──►│  缓存   │ ──►│  数据库  │
└─────────┘    └─────────┘    └─────────┘

分布式缓存架构:
                    ┌─────────────┐
                    │   客户端     │
                    └──────┬──────┘

                    ┌──────▼──────┐
                    │  缓存代理    │
                    │ (Twemproxy) │
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ▼            ▼            ▼
        ┌─────────┐  ┌─────────┐  ┌─────────┐
        │ Redis-1 │  │ Redis-2 │  │ Redis-3 │
        │ (分片1) │  │ (分片2) │  │ (分片3) │
        └─────────┘  └─────────┘  └─────────┘
              │            │            │
              └────────────┼────────────┘

                    ┌─────────────┐
                    │   数据库     │
                    └─────────────┘

Redis 集群架构

Redis Cluster(3主3从):

┌─────────────────────────────────────────────────┐
│                  Redis Cluster                   │
├─────────────────┬─────────────────┬─────────────┤
│                 │                 │             │
▼                 ▼                 ▼             │
┌─────────┐   ┌─────────┐   ┌─────────┐          │
│ Master1 │   │ Master2 │   │ Master3 │          │
│ 0-5460  │   │5461-10922│   │10923-16383│        │
└────┬────┘   └────┬────┘   └────┬────┘          │
     │             │             │                │
     ▼             ▼             ▼                │
┌─────────┐   ┌─────────┐   ┌─────────┐          │
│ Slave1  │   │ Slave2  │   │ Slave3  │          │
└─────────┘   └─────────┘   └─────────┘          │

16384 个槽位,均匀分布在 3 个 Master 上            │
每个 Master 负责一部分槽位                         │
└─────────────────────────────────────────────────┘

缓存穿透、击穿、雪崩

问题原因解决方案
缓存穿透查询不存在的数据布隆过滤器、空值缓存
缓存击穿热点 key 过期互斥锁、逻辑过期
缓存雪崩大量 key 同时过期随机过期时间、多级缓存
// 缓存穿透:布隆过滤器
@Component
public class BloomFilterCache {
    
    private BloomFilter<String> bloomFilter;
    
    @PostConstruct
    public void init() {
        // 预计元素数量 100 万,误判率 0.01%
        bloomFilter = BloomFilter.create(
            Funnels.stringFunnel(Charset.defaultCharset()),
            1000000,
            0.0001
        );
        // 初始化加载所有 key
        List<String> allKeys = productService.getAllKeys();
        allKeys.forEach(bloomFilter::put);
    }
    
    public Product getProduct(String key) {
        // 先判断 key 是否可能存在
        if (!bloomFilter.mightContain(key)) {
            return null;  // 一定不存在
        }
        // 可能存在,查询缓存
        return cacheService.get(key);
    }
}
 
// 缓存击穿:互斥锁
public Product getHotProduct(String key) {
    Product product = redis.get(key);
    if (product != null) {
        return product;
    }
    
    // 获取互斥锁
    String lockKey = "lock:" + key;
    try {
        boolean locked = redis.setnx(lockKey, "1", 10);
        if (locked) {
            // 查询数据库
            product = db.query(key);
            redis.set(key, product, 3600);
        } else {
            // 等待重试
            Thread.sleep(50);
            return getHotProduct(key);
        }
    } finally {
        redis.del(lockKey);
    }
    return product;
}
 
// 缓存雪崩:随机过期时间
public void setWithRandomExpire(String key, Object value) {
    // 基础过期时间 + 随机时间(0-300秒)
    int baseExpire = 3600;
    int randomExpire = ThreadLocalRandom.current().nextInt(300);
    redis.set(key, value, baseExpire + randomExpire);
}

消息队列削峰填谷

削峰架构

削峰填谷流程:

高峰期:
┌─────────┐    ┌─────────┐    ┌─────────┐
│  用户   │ ──►│  网关   │ ──►│ 消息队列 │
│ (100万) │    │ (限流)  │    │ (缓冲)  │
└─────────┘    └─────────┘    └────┬────┘

                   ┌────────────────┼────────────────┐
                   ▼                ▼                ▼
              ┌─────────┐     ┌─────────┐     ┌─────────┐
              │ 消费者1  │     │ 消费者2  │     │ 消费者3  │
              │ (1万/s) │     │ (1万/s) │     │ (1万/s) │
              └─────────┘     └─────────┘     └─────────┘

削峰效果:
- 入口流量:10万 QPS
- 消费速度:3万 QPS
- 消息队列缓冲:处理流量洪峰
// 削峰填谷实现
@RestController
public class OrderController {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    // 下单请求直接写入消息队列
    @PostMapping("/order")
    public Result createOrder(@RequestBody OrderRequest request) {
        // 快速响应
        rabbitTemplate.convertAndSend(
            "order.exchange",
            "order.create",
            request
        );
        return Result.success("订单提交成功,正在处理");
    }
}
 
// 消费者按固定速率处理
@Component
@RabbitListener(queues = "order.queue")
public class OrderConsumer {
    
    @RabbitHandler
    public void handleOrder(OrderRequest request) {
        // 控制消费速率
        orderService.processOrder(request);
    }
}

数据库分库分表

分库分表策略

策略说明优点缺点
垂直分库按业务拆分业务隔离、独立扩展跨库 JOIN 困难
垂直分表按字段拆分宽表变窄表需要关联查询
水平分库按数据行拆分数据分散、性能提升跨库事务复杂
水平分表单表数据拆分单表性能提升需要路由规则
垂直分库:
┌─────────────────────────────────────────────────┐
│                  单库(拆分前)                   │
│  用户表、订单表、商品表、支付表、库存表            │
└─────────────────────────────────────────────────┘

                        ▼ 拆分
┌────────────┐ ┌────────────┐ ┌────────────┐
│   用户库    │ │   订单库    │ │   商品库    │
│  用户表     │ │  订单表     │ │  商品表     │
│            │ │  支付表     │ │  库存表     │
└────────────┘ └────────────┘ └────────────┘

水平分表:
┌─────────────────────────────────────────────────┐
│              订单表(拆分前:1亿数据)             │
└─────────────────────────────────────────────────┘

                        ▼ 按 user_id 取模拆分
┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ order_0    │ │ order_1    │ │ order_2    │ │ order_3    │
│ user_id%4=0│ │ user_id%4=1│ │ user_id%4=2│ │ user_id%4=3│
│ 2500万数据 │ │ 2500万数据 │ │ 2500万数据 │ │ 2500万数据 │
└────────────┘ └────────────┘ └────────────┘ └────────────┘

ShardingSphere 配置

# ShardingSphere 分库分表配置
spring:
  shardingsphere:
    datasource:
      names: ds0,ds1
      ds0:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/db0
      ds1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/db1
    
    rules:
      sharding:
        tables:
          t_order:
            # 分表配置
            actual-data-nodes: ds$->{0..1}.t_order_$->{0..3}
            # 分库策略
            database-strategy:
              standard:
                sharding-column: user_id
                sharding-algorithm-name: order_db_inline
            # 分表策略
            table-strategy:
              standard:
                sharding-column: order_id
                sharding-algorithm-name: order_table_inline
        
        sharding-algorithms:
          order_db_inline:
            type: INLINE
            props:
              algorithm-expression: ds$->{user_id % 2}
          order_table_inline:
            type: INLINE
            props:
              algorithm-expression: t_order_$->{order_id % 4}

读写分离

读写分离架构

读写分离架构:
                    ┌─────────────┐
                    │   应用层     │
                    └──────┬──────┘

                    ┌──────▼──────┐
                    │  数据库代理  │
                    │ (ShardingSphere)│
                    └──────┬──────┘
              ┌────────────┼────────────┐
              ▼            │            ▼
        ┌─────────┐        │      ┌─────────┐
        │ Master  │ ───────┼──────►│ Slave1  │
        │ (写)    │        │      │ (读)    │
        └────┬────┘        │      └─────────┘
             │             │
             │        ┌────▼────┐
             │        │ Slave2  │
             │        │ (读)    │
             │        └─────────┘

      主从复制(异步)
# ShardingSphere 读写分离配置
spring:
  shardingsphere:
    rules:
      readwrite-splitting:
        data-sources:
          myds:
            write-data-source-name: master
            read-data-source-names: slave0,slave1
            load-balancer-name: round_robin
        load-balancers:
          round_robin:
            type: ROUND_ROBIN
// 强制走主库(需要读最新数据)
@Transactional(readOnly = false)
@ShardingSphereHint("write")
public Order getLatestOrder(Long userId) {
    return orderMapper.selectLatest(userId);
}

三、微服务架构

微服务拆分原则

拆分维度

拆分方式说明示例
按业务拆分按业务领域划分用户服务、订单服务、商品服务
按领域拆分DDD 领域驱动设计用户域、订单域、支付域
按子域拆分核心域、支撑域、通用域商品域(核心)、短信域(通用)
单体架构 → 微服务架构:

单体架构:
┌───────────────────────────────────────┐
│            单体应用                     │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐    │
│  │用户 │ │订单 │ │商品 │ │支付 │    │
│  └─────┘ └─────┘ └─────┘ └─────┘    │
│              ↓                       │
│         单一数据库                     │
└───────────────────────────────────────┘

微服务架构:
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│用户服务  │ │订单服务  │ │商品服务  │ │支付服务  │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘
     │           │           │           │
     ▼           ▼           ▼           ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ 用户库  │ │ 订单库  │ │ 商品库  │ │ 支付库  │
└─────────┘ └─────────┘ └─────────┘ └─────────┘

服务拆分原则

1. 单一职责原则(SRP)
   - 每个服务只负责一个业务功能
   - 服务粒度适中,不要太细也不要太粗

2. 高内聚低耦合
   - 服务内部高内聚
   - 服务之间低耦合
   - 避免循环依赖

3. 边界上下文(Bounded Context)
   - DDD 核心概念
   - 每个服务有自己的边界
   - 同一概念在不同服务可以有不同的模型

4. 数据库独立
   - 每个服务有独立的数据库
   - 禁止跨库 JOIN
   - 通过 API 交互

5. 团队自治
   - 每个服务由独立团队负责
   - 技术栈可以不同
   - 独立部署和扩展

服务注册与发现

注册中心对比

特性NacosEurekaConsulZooKeeper
一致性CP/AP 可选APCPCP
健康检查TCP/HTTP/MySQL心跳TCP/HTTP心跳
配置中心支持不支持支持支持
多语言支持Java支持支持
管理界面丰富简单丰富

Nacos 服务注册发现

# 服务注册配置
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.100:8848
        namespace: dev
        group: DEFAULT_GROUP
        metadata:
          version: 1.0.0
          region: beijing
// 服务发现与调用
@RestController
public class OrderController {
    
    @Autowired
    private DiscoveryClient discoveryClient;
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/order/{id}")
    public Order getOrder(@PathVariable Long id) {
        // 服务发现
        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
        ServiceInstance instance = instances.get(0);
        
        // 服务调用
        String url = instance.getUri() + "/user/" + id;
        return restTemplate.getForObject(url, Order.class);
    }
}
 
// 使用 LoadBalancer 负载均衡
@RestController
public class ProductController {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @GetMapping("/product/{id}")
    public Product getProduct(@PathVariable Long id) {
        // 自动负载均衡
        return restTemplate.getForObject(
            "http://product-service/product/" + id,
            Product.class
        );
    }
}
服务注册发现流程:

1. 服务启动
   ┌──────────┐
   │ 服务提供者 │
   └─────┬────┘
         │ 注册

   ┌──────────┐
   │ 注册中心  │
   └─────┬────┘
         │ 订阅

   ┌──────────┐
   │ 服务消费者 │
   └──────────┘

2. 服务调用
   服务消费者 → 注册中心 → 获取服务列表
   服务消费者 → 服务提供者 → 发起调用

3. 健康检查
   服务提供者 → 心跳 → 注册中心
   注册中心 → 剔除 → 不健康实例
   注册中心 → 推送 → 服务列表变更

配置中心

Nacos 配置中心

# bootstrap.yml
spring:
  application:
    name: user-service
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.100:8848
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yaml
        shared-configs:
          - data-id: common.yaml
            group: DEFAULT_GROUP
            refresh: true
// 动态配置刷新
@RestController
@RefreshScope
public class ConfigController {
    
    @Value("${app.config.value}")
    private String configValue;
    
    @GetMapping("/config")
    public String getConfig() {
        return configValue;
    }
}

Apollo 配置中心

# application.properties
app.id=user-service
apollo.meta=http://192.168.1.100:8080
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application

服务网关

Spring Cloud Gateway

# 网关配置
spring:
  cloud:
    gateway:
      routes:
        # 用户服务路由
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100
                redis-rate-limiter.burstCapacity: 200
                key-resolver: "#{@userKeyResolver}"
        
        # 订单服务路由
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1
      
      # 全局跨域配置
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
            allowCredentials: true
// 网关过滤器
@Component
public class AuthFilter implements GlobalFilter, Ordered {
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        
        // 1. 检查白名单
        String path = request.getPath().value();
        if (isWhitePath(path)) {
            return chain.filter(exchange);
        }
        
        // 2. 验证 Token
        String token = request.getHeaders().getFirst("Authorization");
        if (StringUtils.isEmpty(token)) {
            return unauthorized(exchange);
        }
        
        // 3. 解析用户信息
        try {
            UserInfo user = JwtUtil.parse(token);
            ServerHttpRequest newRequest = request.mutate()
                .header("X-User-Id", user.getUserId())
                .build();
            return chain.filter(exchange.mutate().request(newRequest).build());
        } catch (Exception e) {
            return unauthorized(exchange);
        }
    }
    
    @Override
    public int getOrder() {
        return -100;
    }
}

分布式事务

分布式事务方案对比

方案一致性性能复杂度适用场景
2PC强一致传统数据库
3PC强一致传统数据库
TCC最终一致高并发业务
Saga最终一致长流程业务
本地消息表最终一致简单场景
事务消息最终一致高并发场景

Seata 分布式事务

Seata 架构:

┌─────────────────────────────────────────────────┐
│                    TM (事务管理器)                │
│                  开启/提交/回滚全局事务            │
└────────────────────────┬────────────────────────┘


┌─────────────────────────────────────────────────┐
│                    TC (事务协调器)                │
│              Seata Server (调度中心)             │
└────────┬────────────────────────────────────────┘
         │                        │
         ▼                        ▼
┌─────────────────┐      ┌─────────────────┐
│   RM (资源管理器) │      │   RM (资源管理器) │
│    订单服务       │      │    库存服务       │
└─────────────────┘      └─────────────────┘
// Seata AT 模式
@Service
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private StockClient stockClient;
    
    @Autowired
    private AccountClient accountClient;
    
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    @Override
    public void createOrder(OrderDTO orderDTO) {
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        orderMapper.insert(order);
        
        // 2. 扣减库存
        stockClient.decrement(orderDTO.getProductId(), orderDTO.getCount());
        
        // 3. 扣减余额
        accountClient.debit(orderDTO.getUserId(), orderDTO.getAmount());
        
        // 任意一步失败,自动回滚所有操作
    }
}
// TCC 模式
@LocalTCC
public interface StockTccService {
    
    @TwoPhaseBusinessAction(name = "prepareDeduct", commitMethod = "commit", rollbackMethod = "rollback")
    boolean prepareDeduct(@BusinessActionContextParameter(paramName = "productId") Long productId,
                          @BusinessActionContextParameter(paramName = "count") Integer count);
    
    boolean commit(BusinessActionContext context);
    
    boolean rollback(BusinessActionContext context);
}
 
// 实现
@Service
public class StockTccServiceImpl implements StockTccService {
    
    @Autowired
    private StockMapper stockMapper;
    
    @Autowired
    private StockFreezeMapper stockFreezeMapper;
    
    @Override
    public boolean prepareDeduct(Long productId, Integer count) {
        // 1. 扣减可用库存
        int rows = stockMapper.decrement(productId, count);
        if (rows == 0) {
            throw new RuntimeException("库存不足");
        }
        
        // 2. 记录冻结库存
        StockFreeze freeze = new StockFreeze();
        freeze.setProductId(productId);
        freeze.setCount(count);
        stockFreezeMapper.insert(freeze);
        
        return true;
    }
    
    @Override
    public boolean commit(BusinessActionContext context) {
        Long productId = context.getActionContext("productId", Long.class);
        Integer count = context.getActionContext("count", Integer.class);
        
        // 删除冻结记录
        stockFreezeMapper.delete(productId, count);
        return true;
    }
    
    @Override
    public boolean rollback(BusinessActionContext context) {
        Long productId = context.getActionContext("productId", Long.class);
        Integer count = context.getActionContext("count", Integer.class);
        
        // 1. 恢复可用库存
        stockMapper.increment(productId, count);
        
        // 2. 删除冻结记录
        stockFreezeMapper.delete(productId, count);
        
        return true;
    }
}

分布式链路追踪

SkyWalking 架构

SkyWalking 架构:

┌──────────┐ ┌──────────┐ ┌──────────┐
│ 服务 A   │ │ 服务 B   │ │ 服务 C   │
└────┬─────┘ └────┬─────┘ └────┬─────┘
     │            │            │
     └────────────┼────────────┘
                  │ 上报数据

         ┌───────────────┐
         │    OAP Server  │
         │   (分析处理)    │
         └───────┬───────┘
                 │ 存储

         ┌───────────────┐
         │   Elasticsearch│
         └───────┬───────┘
                 │ 查询

         ┌───────────────┐
         │      UI       │
         │   (可视化)     │
         └───────────────┘

链路追踪概念

Trace(追踪):
- 一次完整请求的链路
- 包含多个 Span
- TraceID 全局唯一

Span(跨度):
- 一个服务调用单元
- 包含服务名、方法名、耗时
- 有父子关系

示例:
请求 → 网关 → 用户服务 → 订单服务 → 库存服务

TraceID: abc123
SpanID: 1 (网关) → 2 (用户服务) → 3 (订单服务) → 4 (库存服务)
       ↑              ↑              ↑              ↑
      0ms           10ms           50ms           80ms

使用示例

// 自定义链路追踪
@RestController
public class TraceController {
    
    @Autowired
    private Tracer tracer;
    
    @GetMapping("/trace")
    public String trace() {
        // 创建 Span
        Span span = tracer.spanBuilder("custom-operation")
            .setAttribute("attr.key", "value")
            .startSpan();
        
        try (Scope scope = span.makeCurrent()) {
            // 业务逻辑
            doSomething();
        } finally {
            span.end();
        }
        
        return "success";
    }
}

四、云原生架构

容器化部署

Docker 容器化

# 多阶段构建
# 构建阶段
FROM maven:3.8-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
 
# 运行阶段
FROM openjdk:17-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
 
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1
 
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
# docker-compose.yml
version: '3.8'
services:
  user-service:
    build: ./user-service
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - NACOS_SERVER_ADDR=nacos:8848
    depends_on:
      - nacos
      - mysql
    networks:
      - app-network
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 1G
 
networks:
  app-network:
    driver: bridge

Kubernetes 部署

# Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: user-service:latest
        ports:
        - containerPort: 8080
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: NACOS_SERVER_ADDR
          valueFrom:
            configMapKeyRef:
              name: app-config
              key: nacos.addr
 
---
# Service
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - port: 8080
    targetPort: 8080
  type: ClusterIP
 
---
# HPA(自动扩缩容)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: user-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: user-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70

服务网格(Istio)

Istio 架构:

                    ┌─────────────────────────────────────┐
                    │            Istio 控制平面            │
                    │  ┌─────────┐ ┌─────────┐ ┌───────┐ │
                    │  │ Pilot   │ │ Citadel │ │ Galley│ │
                    │  │(流量管理)│ │(安全)   │ │(配置) │ │
                    │  └─────────┘ └─────────┘ └───────┘ │
                    └─────────────────┬───────────────────┘
                                      │ 下发配置

┌─────────────────────────────────────────────────────────────────┐
│                        Istio 数据平面                            │
│  ┌──────────────────┐    ┌──────────────────┐                  │
│  │   Pod: Service A  │    │   Pod: Service B  │                  │
│  │ ┌──────┐ ┌──────┐│    │ ┌──────┐ ┌──────┐│                  │
│  │ │ Envoy│ │服务A ││◄───►│ │ Envoy│ │服务B ││                  │
│  │ │(Sidecar)│       ││    │ │(Sidecar)│       ││                  │
│  │ └──────┘ └──────┘│    │ └──────┘ └──────┘│                  │
│  └──────────────────┘    └──────────────────┘                  │
└─────────────────────────────────────────────────────────────────┘
# Istio 虚拟服务
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: user-service
spec:
  hosts:
  - user-service
  http:
  - route:
    - destination:
        host: user-service
        subset: v1
      weight: 90
    - destination:
        host: user-service
        subset: v2
      weight: 10  # 10% 流量到 v2(金丝雀发布)
    retries:
      attempts: 3
      perTryTimeout: 2s
    timeout: 5s
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: user-service
spec:
  host: user-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
      http:
        h2UpgradePolicy: UPGRADE
        http1MaxPendingRequests: 100
        http2MaxRequests: 1000
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 30s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

Serverless 架构

Serverless 架构:

传统架构:
┌─────────────────────────────────────┐
│           服务器 (24h 运行)          │
│  ┌─────────┐ ┌─────────┐           │
│  │ 服务 A  │ │ 服务 B  │           │
│  └─────────┘ └─────────┘           │
│           固定成本                   │
└─────────────────────────────────────┘

Serverless 架构:
┌─────────────────────────────────────┐
│            云平台                    │
│  ┌─────────┐     ┌─────────┐       │
│  │ 函数 A  │     │ 函数 B  │       │
│  │(按需运行)│     │(按需运行)│       │
│  └─────────┘     └─────────┘       │
│        按实际调用付费               │
└─────────────────────────────────────┘
// AWS Lambda 示例
public class OrderHandler implements RequestHandler<Map<String, Object>, String> {
    
    @Override
    public String handleRequest(Map<String, Object> input, Context context) {
        // 获取触发器信息
        String orderId = (String) input.get("orderId");
        
        // 处理订单
        OrderService orderService = new OrderService();
        orderService.processOrder(orderId);
        
        return "Order processed: " + orderId;
    }
}
 
// 阿里云函数计算示例
public class HttpHandler implements HttpRequestHandler {
    
    @Override
    public void handleRequest(HttpRequest request, HttpResponse response, Context context) {
        // 获取请求参数
        String body = request.getBody();
        
        // 处理请求
        String result = processRequest(body);
        
        // 返回响应
        response.setStatus(200);
        response.setContentType("application/json");
        response.setBody(result);
    }
}

五、架构设计原则

高可用设计原则

1. 消除单点故障
   - 多副本部署
   - 多机房部署
   - 负载均衡

2. 快速故障转移
   - 健康检查
   - 自动摘除
   - 快速恢复

3. 降级熔断
   - 服务降级
   - 熔断保护
   - 限流控制

4. 数据备份
   - 主从复制
   - 数据备份
   - 灾备恢复

5. 监控告警
   - 实时监控
   - 快速告警
   - 快速定位

高并发设计原则

1. 垂直扩展
   - 提升单机性能
   - CPU、内存、磁盘
   - 有上限

2. 水平扩展
   - 增加服务器数量
   - 理论无上限
   - 需要无状态设计

3. 缓存优化
   - 多级缓存
   - 缓存预热
   - 缓存穿透/击穿/雪崩处理

4. 异步处理
   - 消息队列
   - 削峰填谷
   - 最终一致性

5. 分库分表
   - 数据分散
   - 提升单表性能
   - 读写分离

微服务设计原则

1. 服务拆分
   - 单一职责
   - 高内聚低耦合
   - 边界清晰

2. 服务治理
   - 服务注册发现
   - 负载均衡
   - 熔断降级
   - 链路追踪

3. 数据一致性
   - 分布式事务
   - 最终一致性
   - 幂等设计

4. 可观测性
   - 日志收集
   - 指标监控
   - 链路追踪

5. 安全性
   - 认证授权
   - 数据加密
   - 网络隔离

六、面试要点

Q1: 如何设计一个高可用系统?

回答要点

  1. 消除单点:多副本部署、多机房部署
  2. 故障转移:健康检查、自动摘除、快速恢复
  3. 限流熔断:防止雪崩效应
  4. 数据备份:主从复制、灾备恢复
  5. 监控告警:实时监控、快速响应

Q2: 如何设计一个高并发系统?

回答要点

  1. 负载均衡:分发流量到多台服务器
  2. 缓存优化:多级缓存、缓存预热
  3. 异步处理:消息队列削峰填谷
  4. 分库分表:数据分散、提升性能
  5. 读写分离:分离读写压力

Q3: 微服务拆分的原则是什么?

回答要点

  1. 单一职责:每个服务只负责一个业务功能
  2. 高内聚低耦合:服务内部紧密相关,服务之间松散依赖
  3. 边界清晰:DDD 领域驱动设计
  4. 数据库独立:每个服务有独立的数据库
  5. 团队自治:独立团队负责、独立部署扩展

Q4: 什么是 CAP 理论?

回答要点

  • Consistency(一致性):所有节点同一时间看到相同的数据
  • Availability(可用性):每个请求都能得到响应
  • Partition Tolerance(分区容错性:网络分区时系统仍能运行
  • 三选二:分布式系统最多只能同时满足两个

Q5: 什么是分布式事务?有哪些解决方案?

回答要点

  • 定义:跨多个数据库/服务的事务
  • 方案
    • 2PC/3PC:强一致,性能低
    • TCC:最终一致,性能高,实现复杂
    • Saga:长流程事务,补偿机制
    • 事务消息:高并发场景,最终一致
    • Seata:开源分布式事务框架

Q6: 什么是服务网格?有什么优势?

回答要点

  • 定义:基础设施层,处理服务间通信
  • 核心组件:数据平面(Envoy)、控制平面(Istio)
  • 优势
    • 语言无关:支持多语言
    • 流量管理:路由、重试、超时
    • 安全通信:mTLS 加密
    • 可观测性:日志、指标、追踪

Q7: 如何保证缓存和数据库的一致性?

回答要点

  1. Cache Aside:先更新数据库,再删除缓存
  2. 延迟双删:删除缓存 → 更新数据库 → 延迟删除缓存
  3. 消息队列:通过消息队列保证最终一致
  4. Binlog 订阅:Canal 订阅 Binlog 异步更新缓存
  5. 设置过期时间:作为兜底方案

Q8: 什么是熔断?熔断器有哪些状态?

回答要点

  • 定义:当下游服务故障时,快速失败,避免级联故障
  • 状态
    • Closed(关闭):正常状态
    • Open(打开):熔断状态,快速失败
    • Half-Open(半开):探测恢复状态
  • 触发条件:错误率、超时率、响应时间

小结

  • 高可用设计核心:消除单点、快速故障转移、限流熔断降级
  • 高并发架构核心:负载均衡、缓存优化、异步处理、分库分表
  • 微服务核心:服务拆分、服务治理、分布式事务、可观测性
  • 云原生架构:容器化、服务网格、Serverless
  • 架构设计原则:权衡取舍,没有银弹,适合业务的才是最好的