Featured image of post 微服务中间件集群实战:Nacos / Gateway / MySQL / Redis / MQ

微服务中间件集群实战:Nacos / Gateway / MySQL / Redis / MQ

5 大微服务中间件集群部署实战:Spring Cloud Gateway + Nginx 负载均衡、Nacos 3 节点集群、MySQL 主从复制 + 读写分离、Redis 3 种集群模式、RabbitMQ/RocketMQ 消息集群

本文写于 2021 年 9 月——微服务架构全面铺开,Nacos 2.0+ 已发布一年(2020 年初)、Spring Cloud Gateway 已成事实标准(替代 Zuul)、Redis Cluster 在生产大规模使用,5 大微服务中间件的"集群"方案成为面试必考点。

〇、2021 视角开篇

本文主体内容是 5 大微服务中间件(Gateway / Nacos / MySQL / Redis / MQ)的集群部署实战。2021-09 这个时点选得很巧

  • Nacos 2.0(2020-01 发布)刚满 1.5 年,集群方案已稳定(Distro + Raft 双协议)
  • Spring Cloud Gateway(2018 年发布)替代 Zuul 已成定局,2021.x 是生产主流
  • Redis Cluster(3.0 起)经过 4 年迭代,3 主 3 从 6 节点模式是生产标配
  • RocketMQ 4.x(2017 年起)多主多从模式是阿里系标配,Kafka 同期竞争

下文涉及 2016 年时实际并不存在的工具(Nacos / Spring Cloud Gateway),是以 2021 视角讲解"这些工具是何时出现、何时成熟、2021 时点怎么用"。

一、Spring Cloud Gateway 集群

1.1 概述

Spring Cloud Gateway 是 Spring Cloud 的全新项目,基于 Spring 5.0 + Spring Boot 2.0 实现,旨在提供一种简单有效的方式对 API 进行路由,并提供强大的过滤功能:熔断、限流、监控、校验、鉴权

为什么取代 Zuul?

  • Zuul 1.x 基于 Servlet 阻塞模型,性能有限
  • Zuul 2.0 跳票多年(被 Netflix 弃坑),Spring 社区转向基于 WebFlux + Netty 的响应式网关
  • Gateway 基于 WebFlux 框架,底层用 Netty 通信框架,性能远超 Zuul

1.2 集群部署

Gateway 是无状态服务,集群化非常简单:多实例 + 统一入口

第一步:pom.xml 依赖

1
2
3
4
5
6
7
8
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

第二步:application.yml 配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    nacos:
      discovery:
        server-addr: nacos-cluster.internal:8848   # Nacos 集群地址
    gateway:
      discovery:
        locator:
          enabled: true              # 开启从注册中心自动创建路由
      routes:
        - id: payment_route
          uri: lb://cloud-payment-service   # lb = load balance
          predicates:
            - Path=/payment/**

第三步:Nginx 入口负载均衡

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
upstream gateways {
    server 192.168.6.29:9527 weight=1;
    server 192.168.6.29:9528 weight=1;  # 同一台机器两个端口模拟集群
    # server 192.168.6.30:9527 weight=1;  # 多机部署
}

server {
    listen 80;
    server_name api.example.com;
    location / {
        proxy_pass http://gateways;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

关键点

  • Gateway 实例之间不需要通信,各自从 Nacos 拉服务列表
  • 网关自身的负载均衡交给 Nginx / F5 / SLB
  • 网关是无状态服务,可以水平扩展

二、Nacos 集群

2.1 三种部署模式

  • 单机模式:用于测试和单机使用
  • 集群模式:用于生产环境,确保高可用
  • 多集群模式:用于多数据中心场景

2.2 集群部署(Nacos ≥ 2.0)

前置:nacos 集群至少需要 3 个节点,因此准备 3 台服务器。

第一步:安装依赖

1
2
3
# 1. 安装 MySQL(nacos 配置持久化)
# 2. 安装 JDK 8+
# 3. 安装 Maven(仅首次构建时需要)

第二步:初始化数据库

执行 nacos 自带 SQL:conf/nacos-mysql.sql,创建 nacos_config 数据库和表。

第三步:配置 cluster.conf

conf/cluster.conf.example 改名为 cluster.conf

1
2
3
4
# cluster.conf
192.168.6.21:8848
192.168.6.22:8848
192.168.6.23:8848

第四步:配置 application.properties

1
2
3
4
5
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.6.10:3306/nacos_config?useUnicode=true&characterEncoding=utf-8
db.user=nacos
db.password={{REDACTED}}

第五步:启动

1
sh startup.sh

单台服务器启动成功后,对集群其他服务器重复同样操作即可

2.3 集群原理

  • Distro 协议(AP 模式,默认):nacos 自研的最终一致协议,每个节点负责一部分服务,多节点互写互读
  • Raft 协议(CP 模式,配置中心):持久化配置走 Raft,保证强一致
  • 节点间通过 gRPC 长连接 同步数据

三、MySQL 主从集群

3.1 集群目的

采用 MySQL 集群需要部署主从关系

  • 主节点:写数据(INSERT / UPDATE / DELETE)
  • 从节点:读数据(SELECT)
  • 关系:一主多从,用户从多个从节点读数据,大大缓解读取压力
  • 额外收益:主节点写入自动同步到从节点,降低数据丢失风险

3.2 主从复制原理

MySQL 主从复制基于主服务器二进制日志(binlog) 跟踪所有对数据库的更改。

工作过程

1
2
3
4
5
6
7
8
9
┌─────────┐                                 ┌─────────┐
│  Master │                                 │  Slave  │
│         │                                 │         │
│  binlog │ <── (1) 读 binlog ─── I/O 线程 ──│  relay  │
│  dump   │                                 │   log   │
│  线程   │ ── (2) 传 binlog ───────────>   │         │
│         │                                 │  SQL 线程│
│         │ <── (3) 同步完成通知 ───────────│         │
└─────────┘                                 └─────────┘
  1. 从库生成两个线程:一个 I/O 线程,一个 SQL 线程
  2. I/O 线程请求主库的 binlog,并将 binlog 写到 relay log(中继日志)
  3. 主库生成 log dump 线程,用来给从库 I/O 线程传 binlog
  4. SQL 线程读取 relay log,解析成具体操作,实现主从一致

3.3 核心配置

主库 my.cnf

1
2
3
4
5
[mysqld]
server-id = 1
log-bin = /var/lib/mysql/mysql-bin
binlog-format = ROW
sync_binlog = 1

从库 my.cnf

1
2
3
4
[mysqld]
server-id = 2
relay-log = /var/lib/mysql/relay-log
read-only = 1

主库授权

1
2
grant replication slave on *.* to 'repl_user'@'%' identified by '{{REDACTED}}';
flush privileges;

从库配置同步

1
2
3
4
5
6
7
8
9
CHANGE MASTER TO
  MASTER_HOST='192.168.6.21',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='{{REDACTED}}',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=0;

START SLAVE;
SHOW SLAVE STATUS\G   #  Slave_IO_Running: Yes, Slave_SQL_Running: Yes

3.4 读写分离

两种实现方式

  1. 数据库中间件(Mycat / Sharding-Proxy):单独部署服务,配置实现读写分离,不侵入业务代码
  2. 客户端 SDK(dynamic-datasource / shardingsphere-jdbc):业务代码引入 jar 包,通过注解切换

dynamic-datasource 示例(Spring Boot):

1
2
3
4
5
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.3.2</version>
</dependency>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
spring:
  datasource:
    dynamic:
      primary: master
      datasource:
        master:
          url: jdbc:mysql://192.168.6.21:3306/test
          username: root
          password: {{REDACTED}}
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave1:
          url: jdbc:mysql://192.168.6.22:3306/test
          username: root
          password: {{REDACTED}}
          driver-class-name: com.mysql.cj.jdbc.Driver
1
2
3
4
5
6
7
8
@Service
public class OrderService {
    @DS("master")  // 写主库
    public void createOrder(Order order) { ... }
    
    @DS("slave1")  // 读从库
    public List<Order> listOrders() { ... }
}

3.5 分库分表

两种方案:

  • Sharding Sphere(推荐):JDBC 代理 / Proxy 模式
  • Mycat 2:数据库中间件,需要独立部署

四、Redis 集群

4.1 三种集群方案

  • 主从复制模式:1 主 N 从,主写从读,但主挂了不会自动切换(需要手动)
  • Sentinel(哨兵)模式:在主从基础上加哨兵进程监控,主挂了自动选举新主(推荐中小规模)
  • Cluster 模式:Redis 3.0+ 官方方案,数据分片 + 主从 + 自动故障转移(推荐大规模)

4.2 集群部署(Cluster 模式)

官方推荐:集群至少 3 个 master 节点,最好用 3 主 3 从 6 节点模式

1
2
3
4
5
6
# 启用集群模式
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
# 至少 3 个 master
cluster-migration-barrier 1

创建集群

1
2
3
4
redis-cli --cluster create \
  192.168.6.31:6379 192.168.6.32:6379 192.168.6.33:6379 \
  192.168.6.34:6379 192.168.6.35:6379 192.168.6.36:6379 \
  --cluster-replicas 1

4.3 Cluster 原理

  • 数据分片:16384 个 slot(哈希槽),每个 master 负责一段
  • 请求路由:客户端通过 CRC16(key) % 16384 计算 slot
  • 重定向:如果请求路由到错误节点,会返回 MOVEDASK 让客户端重试
  • 故障转移:master 挂了,从节点通过 Raft-like 协议选举新主

五、消息队列集群

5.1 RabbitMQ 集群

  • 普通集群:多节点共享元数据,队列只在单节点,性能提升有限
  • 镜像集群:队列数据多节点同步,HA 能力强但性能低
  • 推荐方案:普通集群 + HAProxy + 镜像队列(关键业务队列)

5.2 RocketMQ 集群

  • NameServer 集群:无状态,多节点即可
  • Broker 集群:分 Master / Slave
    • 多 Master:高性能但无 HA
    • 多 Master 多 Slave(异步复制):性能 + HA 平衡
    • 多 Master 多 Slave(同步双写):强 HA,性能低
  • 推荐方案:2 主 2 异步从 + 异步刷盘

六、5 大集群对比

集群核心协议关键配置HA 能力数据一致性
Gateway无(无状态)Nginx upstream自动(多实例)无(无状态)
NacosDistro + Raftcluster.conf + MySQL自动(≥3 节点)AP+CP 混合
MySQLbinlog + relay logserver-id + log-bin半自动(需切换)最终一致
Redis Cluster哈希槽(16384)cluster-enabled自动(≥3 master)最终一致
RabbitMQ镜像队列cluster_partition_handling自动(镜像)最终一致
RocketMQ主从同步brokerRole自动(多主多从)异步/同步

七、面试常问

Q:为什么 Nacos 集群至少 3 个节点? A:Raft 协议要求过半节点存活才能选举 Leader,3 节点允许 1 节点宕机,5 节点允许 2 节点宕机。奇数节点是性价比最高的选择

Q:MySQL 主从延迟怎么解决? A:① 业务容忍延迟(异步复制天然有 ms 级延迟);② 强制读主(重要业务读写都走主);③ 半同步复制(MySQL 5.7+ rpl_semi_sync_master_wait_slave_count);④ 用 Canal 订阅 binlog 同步到 ES / Redis。

Q:Redis Cluster 为什么是 16384 个 slot? A:因为 16384 足够均匀分布,节点间心跳包大小可控(每个 slot 1 bit,16384 / 8 = 2KB,远小于 1MB 网络包上限)。如果用 65536,心跳包会膨胀到 8KB,且实际场景下节点数不会超过 1000,16384 足够。

Q:Spring Cloud Gateway 怎么限流? A:内置 RequestRateLimiter GatewayFilter,基于 Redis + Lua 脚本实现令牌桶。Key 可以基于 IP / User / API Path。

八、小结

  • Gateway 无状态:集群 = 多实例 + 入口 LB
  • Nacos 集群:3 节点起步 + MySQL 持久化
  • MySQL 主从:binlog 同步 + 读写分离中间件
  • Redis Cluster:16384 哈希槽 + 3 主 3 从
  • MQ 集群:RabbitMQ 镜像队列 / RocketMQ 多主多从

九、2021 视角回望(微服务面试考点演化)

站在 2021-09 收尾,回看"5 大集群对比"那一节,再补充几点2021 时点的面试新趋势

  1. Nacos 2.0 的 gRPC 长连接:2020 年 Nacos 2.0 把数据同步从 HTTP 短连接改成长连接,性能提升 10 倍,是高频面试追问点
  2. Spring Cloud Gateway 限流细节:内置 RequestRateLimiter + Redis Lua 是高频八股文,几乎所有 Java 面试都会问
  3. MySQL 5.7 → 8.0 升级:2021 年 5.7 EOL 时间已定(2023-10),8.0 的 MGR(MySQL Group Replication)开始被生产采用
  4. Redis 6.x 的多线程 IO:2020 年 Redis 6.0 发布,IO 多线程化但执行命令仍单线程,集群方案未变
  5. Kafka vs RocketMQ 二选一:阿里系项目用 RocketMQ(事务消息),其他用 Kafka(生态 + 吞吐),2021 年仍是常见面试题

2021 时点的"5 大集群面试"标准答案

  • Gateway 无状态 → 集群 = Nginx upstream + 多实例
  • Nacos 集群 → 至少 3 节点(过半选举) + MySQL 持久化 + gRPC 2.0 同步
  • MySQL 主从 → binlog + relay log + 读写分离(ShardingSphere / dynamic-datasource)
  • Redis Cluster → 16384 哈希槽 + 3 主 3 从 + 客户端路由
  • MQ 集群 → RabbitMQ 镜像队列 / RocketMQ 多主多从(同步双写保 HA)
使用 Hugo 构建
主题 StackJimmy 设计