Skip to content

Spring Cloud 微服务概述与 Nacos

一、微服务概述

单体 vs 微服务

┌─────────────────────────────────────────────────────────────────┐
│                       单体架构                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                     单一应用                              │   │
│  │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐    │   │
│  │  │ 用户模块 │  │ 订单模块 │  │ 支付模块 │  │ 商品模块 │    │   │
│  │  └─────────┘  └─────────┘  └─────────┘  └─────────┘    │   │
│  │  ┌─────────────────────────────────────────────────┐    │   │
│  │  │                   共用数据层                      │    │   │
│  │  └─────────────────────────────────────────────────┘    │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
│  问题:                                                         │
│  - 代码耦合,部署困难                                           │
│  - 扩展性差                                                    │
│  - 单点故障                                                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                       微服务架构                                 │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐       │
│  │ 用户服务  │  │ 订单服务  │  │ 支付服务  │  │ 商品服务  │       │
│  │  :8081   │  │  :8082   │  │  :8083   │  │  :8084   │       │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  └────┬─────┘       │
│       │              │              │              │              │
│       └──────────────┴──────────────┴──────────────┘              │
│                              │                                    │
│                       ┌──────┴──────┐                            │
│                       │   网关/注册中心 │                          │
│                       └─────────────┘                            │
│                                                                  │
│  优势:独立部署、独立扩展、技术异构                                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Spring Cloud 组件栈

┌─────────────────────────────────────────────────────────────────┐
│                      Spring Cloud 组件栈                          │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  服务注册/发现                                                   │
│  ├─ Eureka(Netflix,已停止维护)                                 │
│  ├─ Consul(HashiCorp)                                        │
│  └─ Nacos(阿里巴巴)⭐ 推荐                                    │
│                                                                  │
│  服务调用                                                       │
│  ├─ Ribbon(负载均衡,已停止维护)                               │
│  └─ OpenFeign(声明式 HTTP 客户端)⭐                           │
│                                                                  │
│  网关                                                          │
│  ├─ Zuul(Netflix,已停止维护)                                  │
│  └─ Gateway(响应式网关)⭐                                    │
│                                                                  │
│  熔断限流                                                      │
│  ├─ Hystrix(Netflix,已停止维护)                               │
│  └─ Sentinel(阿里巴巴)⭐                                      │
│                                                                  │
│  配置中心                                                      │
│  ├─ Config(Spring Cloud Config)                               │
│  └─ Nacos(同时支持配置中心)⭐                                 │
│                                                                  │
│  消息队列                                                      │
│  ├─ Stream(抽象层)                                           │
│  └─ RocketMQ / Kafka / RabbitMQ                                │
│                                                                  │
│  分布式事务                                                    │
│  └─ Seata(阿里巴巴)⭐                                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

二、Nacos 概述

Nacos 是什么

┌─────────────────────────────────────────────────────────────────┐
│                         Nacos                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Nacos = Naming + Configuration + Service                       │
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                     Nacos                                │   │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐     │   │
│  │  │  服务注册  │  │   配置管理   │  │    流量管理  │     │   │
│  │  │  & 发现    │  │  & 动态配置  │  │  (权重/限流) │     │   │
│  │  └─────────────┘  └─────────────┘  └─────────────┘     │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
│  特性:                                                         │
│  - 易于部署(单机/集群)                                        │
│  - 中文社区活跃                                                │
│  - 同时支持 AP 和 CP                                            │
│  - 集成 Dubbo、Spring Cloud、K8s                                │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

安装 Nacos

bash
# 下载
wget https://github.com/alibaba/nacos/releases/download/2.2.3/nacos-server-2.2.3.tar.gz

# 解压
tar -xzf nacos-server-2.2.3.tar.gz
cd nacos

# 单机启动
sh bin/startup.sh -m standalone

# 访问控制台
# http://localhost:8848/nacos
# 默认账号密码: nacos / nacos

Docker 启动

bash
docker run --name nacos-standalone -e MODE=standalone \
  -p 8848:8848 -p 9848:9848 \
  -d nacos/nacos-server:v2.2.3

三、服务注册与发现

服务提供者

xml
<dependencies>
    <!-- Nacos 服务发现 -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2022.0.0.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

配置

yaml
spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848           # Nacos 地址
        namespace: dev                        # 命名空间(隔离环境)
        group: DEFAULT_GROUP                  # 分组
        enabled: true                         # 启用发现
        register-enabled: true               # 是否注册自身
        ip: 192.168.1.100                    # 注册的 IP(省略则自动获取)
        port: 8080                            # 注册的端口
        
# 服务名/命名空间/分组 组合唯一标识一个服务实例
# ${spring.application.name}:${namespace}:${group}

启动类

java
@SpringBootApplication
@EnableDiscoveryClient  // 启用服务发现
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

健康检查

yaml
spring:
  cloud:
    nacos:
      discovery:
        # 心跳相关配置
        heart-beat-interval: 5000          # 心跳间隔(默认 5000)
        heart-beat-timeout: 15000          # 超时时间(默认 15000)
        ip-delete-timeout: 30000            # 实例删除超时(默认 30000)

四、服务消费者

RestTemplate 调用

java
@Configuration
public class RestTemplateConfig {
    
    @Bean
    @LoadBalanced  // 启用负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Service
public class OrderService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    public Order getOrder(Long orderId) {
        // 使用服务名而非 IP:Port
        String url = "http://user-service/api/user/" + userId;
        User user = restTemplate.getForObject(url, User.class);
        
        // Nacos 会自动发现 user-service 的实例
        // 并进行负载均衡
    }
}

OpenFeign 调用

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
yaml
spring:
  cloud:
    openfeign:
      client:
        config:
          default:          # 全局配置
            logger-level: full
          user-service:    # 指定服务配置
            logger-level: basic
      circuitbreaker:
        enabled: true       # 启用熔断
java
@EnableFeignClients  // 启用 Feign

// 声明式接口
@FeignClient(name = "user-service", path = "/api/users")
public interface UserClient {
    
    @GetMapping("/{id}")
    User getUser(@PathVariable("id") Long id);
    
    @PostMapping
    User createUser(@RequestBody User user);
}

// 使用
@Service
public class OrderService {
    
    @Autowired
    private UserClient userClient;
    
    public Order getOrderWithUser(Long orderId) {
        Order order = orderRepository.findById(orderId);
        User user = userClient.getUser(order.getUserId());
        order.setUser(user);
        return order;
    }
}

五、配置中心

Nacos 配置

xml
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

bootstrap.yml

yaml
spring:
  application:
    name: order-service
  profiles:
    active: dev
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yaml
        refresh-enabled: true  # 启用动态刷新
        
# 配置data-id: ${spring.application.name}-${spring.profiles.active}.${file-extension}
# order-service-dev.yaml

注解方式获取配置

java
@RestController
public class ConfigController {
    
    // 方式1:@Value
    @Value("${app.name}")
    private String appName;
    
    // 方式2:@ConfigurationProperties
    @Autowired
    private AppConfig appConfig;
    
    // 方式3:@NacosValue(支持动态刷新)
    @NacosValue(value = "${app.version}", autoRefreshed = true)
    private String version;
}

@RefreshScope 动态刷新

java
@RestController
@RefreshScope  // 支持动态刷新配置
public class ConfigController {
    
    @Value("${app.config}")
    private String config;
    
    // 当 Nacos 配置变更时,config 会自动更新
}

共享配置

yaml
spring:
  cloud:
    nacos:
      config:
        shared-configs:
          - data-id: common.yaml
            group: COMMON_GROUP
            refresh: true
          - data-id: redis.yaml
            group: COMMON_GROUP
            refresh: false

六、命名空间与分组

命名空间(环境隔离)

Nacos
├── dev 命名空间
│   ├── DEFAULT_GROUP
│   │   ├── user-service
│   │   └── order-service
│   └── PAYMENT_GROUP
│       └── payment-service

├── test 命名空间
│   └── ...

└── prod 命名空间
    └── ...
yaml
spring:
  cloud:
    nacos:
      discovery:
        namespace: dev  # 指定命名空间 ID

分组(业务隔离)

yaml
spring:
  cloud:
    nacos:
      discovery:
        group: USER_GROUP  # 指定分组

七、服务集群

多实例注册

yaml
# 实例1
spring:
  cloud:
    nacos:
      discovery:
        ip: 192.168.1.101
        port: 8080
        cluster-name: HZ  # 杭州集群

# 实例2
spring:
  cloud:
    nacos:
      discovery:
        ip: 192.168.1.102
        port: 8080
        cluster-name: HZ

# 实例3
spring:
  cloud:
    nacos:
      discovery:
        ip: 192.168.1.201
        port: 8080
        cluster-name: SH  # 上海集群

负载均衡

yaml
spring:
  cloud:
    nacos:
      discovery:
        # 优先调用同集群实例
        cluster-name: HZ
        # 权重配置(通过 Nacos 控制台设置)

临时实例 vs 非临时实例

yaml
spring:
  cloud:
    nacos:
      discovery:
        # 临时实例:心跳检测,不存在则移除(默认)
        # 非临时实例:Nacos 主动探测
        ephemeral: false

八、Nacos 集群

集群架构

                    ┌─────────────────┐
                    │     Nginx       │
                    │   (负载均衡)     │
                    └────────┬────────┘

        ┌────────────────────┼────────────────────┐
        │                    │                    │
   ┌────┴────┐          ┌────┴────┐          ┌────┴────┐
   │ Nacos-1 │          │ Nacos-2 │          │ Nacos-3 │
   │ :8848   │◀───────▶│ :8848   │◀───────▶│ :8848   │
   └─────────┘          └─────────┘          └─────────┘
        │                    │                    │
        └────────────────────┼────────────────────┘

                      ┌─────┴─────┐
                      │  MySQL    │
                      │ (共享存储) │
                      └───────────┘

cluster.conf

properties
# 192.168.1.101:8848
# 192.168.1.102:8848
# 192.168.1.103:8848

高可用

选举机制:
1. 集群内选出一个 Leader
2. 所有写操作先同步到 Leader
3. 超过半数节点同步成功则操作成功
4. Leader 挂了重新选举

九、面试高频问题

Q1: Nacos 和 Eureka 区别?

对比NacosEureka
CAP支持 AP 和 CP只支持 AP
健康检查心跳/TCP/HTTP心跳
配置中心支持不支持
活跃度活跃已停止维护
部署单机/集群单机/集群

Q2: AP vs CP 如何选择?

  • AP(可用性):优先保证服务可用,如用户下单
  • CP(一致性):优先保证数据一致,如转账、扣款

Q3: Nacos 配置如何动态刷新?

  1. @RefreshScope 标注 Bean
  2. Nacos 配置变更
  3. Spring Cloud 监听变更事件
  4. 刷新 Bean

Q4: 服务发现流程?

  1. 服务启动时向 Nacos 注册
  2. 定时发送心跳
  3. 消费者从 Nacos 获取服务列表
  4. 本地负载均衡选择实例
  5. 发起调用

十、下一章预告

下一章我们将学习 Gateway 网关

  • Gateway 路由配置
  • 过滤器链
  • 断言(Predicate)
  • 全局过滤器

基于 MIT 许可发布