Skip to content
Home
Go back

Spring Cloud 上手:用 Nacos 注册中心让服务找到彼此

回顾:上篇讲了什么

上一篇我们聊了微服务的核心思想:拆分、自治、解耦、独立演进。理解了这些,再看 Spring Cloud 就不是一套面目模糊的组件清单,而是一套把微服务思想落地的工具集。

但思想终究要在代码里体现。微服务拆开之后,第一个要解决的问题就是:服务之间怎么找到彼此?

这篇就从注册中心入手,用 Nacos 3.x 搭出一个可运行的最小调用链路。

没有注册中心的世界

假如你有两个 Spring Boot 服务:

订单服务在创建订单时需要调用支付服务来完成扣款。

最直接的做法:在 order-service 的配置里写死 payment-service 的地址。

payment:
  url: http://192.168.1.100:8081

一开始还好,但问题很快就来了:

归根结底一句话:调用方不应该手动管理被调用方的地址。

注册中心就是来解决这个问题的。

注册中心解决什么

注册中心在整个微服务架构里扮演通信枢纽的角色,核心职责只有三个:

服务注册

服务启动时主动向注册中心报到,告诉它「我是谁、我在哪」。比如 payment-service 启动后向 Nacos 注册自己的 IP 和端口。

服务发现

调用方不再写死地址,而是向注册中心查询「谁叫 payment-service」。注册中心返回当前可用的实例列表,调用方从中选一个发起请求。

健康检查

注册中心持续检测每个服务实例是否存活。如果某台 payment-service 挂了,注册中心把它从可用列表中摘掉,调用方自然不会请求到这个死实例。

这三个动作构成一个闭环:注册 → 发现 → 健康检查 → 摘除不健康的 → 继续发现健康的。整个过程中,调用方和被调用方完全解耦。

为什么选 Nacos

Spring Cloud 生态里注册中心的选择不少,但现状是这样的:

Nacos(Dynamic Naming and Configuration Service)由阿里巴巴开源,同时覆盖注册中心和配置中心两个场景。它的优势在于:

一句话:对 Spring Cloud 初学者来说,Nacos 是当前「投入产出比」最高的选择。

环境准备

Docker Compose 启动 Nacos

创建一个 docker-compose.yml

version: "3.8"
services:
  nacos:
    image: nacos/nacos-server:v3.2
    container_name: nacos-standalone
    environment:
      - MODE=standalone
      - NACOS_AUTH_TOKEN=${your_nacos_auth_secret_token}
      - NACOS_AUTH_IDENTITY_KEY=${your_nacos_server_identity_key}
      - NACOS_AUTH_IDENTITY_VALUE=${your_nacos_server_identity_value}
    ports:
      - "8080:8080"
      - "8848:8848"
      - "9848:9848"

NACOS_AUTH_TOKEN: Nacos 用于生成JWT Token的密钥,使用长度大于32字符的字符串,再经过Base64编码。

NACOS_AUTH_IDENTITY_KEY: Nacos Server端之间 Inner API的身份标识的Key,必填。

NACOS_AUTH_IDENTITY_VALUE: Nacos Server端之间 Inner API的身份标识的Value,必填。

注意 MODE=standalone。Nacos 有两种运行模式:

模式说明适用场景
standalone单节点运行,数据存内嵌 Derby 数据库本地开发、学习
cluster多节点组成集群,数据存外部 MySQL生产环境

集群模式需要至少三个 Nacos 节点配合 MySQL 做数据持久化,才能保证高可用。对我们学习注册中心来说,standalone 完全够用,启动快、无外部依赖、一台机器就能跑。

启动:

docker compose up -d

启动后访问 http://localhost:8848/nacos,默认用户名密码都是 nacos,看到控制台就说明注册中心已在运行。

Java 与 Maven

假定你本地已有 JDK 17+ 和 Maven,不再赘述安装步骤。

动手:两个服务注册到 Nacos

服务提供者:payment-service

创建一个 Spring Boot 项目,引入依赖:

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

application.yml 中配置 Nacos 地址和服务名:

spring:
  application:
    name: payment-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
server:
  port: 8081

暴露一个简单的接口:

@RestController
public class PaymentController {

    @GetMapping("/pay")
    public String pay() {
        return "Payment successful";
    }
}

启动类上别忘了加 @EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(PaymentServiceApplication.class, args);
    }
}

服务消费者:order-service

同样引入 Nacos Discovery 依赖,配置文件:

spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
server:
  port: 8082

通过 RestTemplate + 服务名调用 payment-service

@Configuration
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/order")
    public String createOrder() {
        // 直接用服务名,不用写 IP:Port
        String result = restTemplate.getForObject(
            "http://payment-service/pay", String.class);
        return "Order created. " + result;
    }
}

注意 @LoadBalanced 注解——它让 RestTemplate 具备客户端负载均衡能力。当 payment-service 有多个实例时,它会自动选择一个可用的来调用。

验证与观察

顺序启动:

# 先确保 Nacos 已在运行
docker compose up -d

# 启动 payment-service
cd payment-service && mvn spring-boot:run

# 启动 order-service
cd order-service && mvn spring-boot:run

打开 Nacos 控制台 http://localhost:8848/nacos,进入「服务管理 → 服务列表」,应该能看到 payment-serviceorder-service 两个服务都已注册。

浏览器访问 http://localhost:8082/order,返回:

Order created. Payment successful

这条调用链路的完整流程:

  1. order-service 收到 /order 请求
  2. 通过 RestTemplatehttp://payment-service/pay 发起调用
  3. @LoadBalanced 拦截请求,从 Nacos 查询 payment-service 的实例列表
  4. 选出一个可用实例(目前只有一个,就是 8081),转发请求
  5. payment-service 处理 /pay 并返回结果

你还可以做个验证:停掉 payment-service,观察 Nacos 控制台——十几秒后该实例会被标记为不健康,order-service 的调用会返回错误。这直观展示了健康检查如何保护调用方。

小结与下篇预告

这一篇我们做了三件事:

  1. 理解注册中心在微服务体系中的角色——服务注册、发现、健康检查
  2. 用 Docker Compose 启动了 Nacos 3.x,并说清了 standalone vs cluster 的选择
  3. 实现了一个完整的最小调用链路:order-service 通过 Nacos 发现 payment-service 并远程调用

现在你手上有一个能跑的微服务雏形。但如果你仔细观察会发现一个问题:@LoadBalanced 目前只有一个实例可选,没有真正发挥负载均衡的价值。

下一篇,我们让 payment-service 跑多个实例,把负载均衡这块讲透。



Previous Post
Spring Cloud 负载均衡:当一个服务有很多实例
Next Post
上手配置一台新的服务器(五):配置日常更新工作流