Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建
Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建
个人主页:夏天拐跑了西瓜
专栏传送门:《大模型应用开发》、《Spring 生态全家桶体系化实战》
学习方向:Java 后端|AI‑Agent 大模型应用开发爱好者
⭐人生格言:路虽远,行则将至

本文是「Spring Cloud 微服务实战」系列的第一篇。文章从单体架构到微服务架构的演变讲起,介绍 Spring Cloud 生态的核心组件,随后基于 Nacos 2.5.1 手把手搭建父工程与订单、库存两个子服务,实现服务注册与发现、按服务名调用,并讲解命名空间、分组与负载均衡机制。读完本文,你可以独立搭建一套基于 Nacos 的微服务调用链路。
系列文章导航
- 《Spring Cloud 微服务实战(一):还在硬编码服务地址?Nacos 注册中心从零搭建》(本篇)
- 《Spring Cloud 微服务实战(二):改个配置还要重启服务?Nacos 配置中心 + OpenFeign 实战》
- 《Spring Cloud 微服务实战(三):一个服务挂了,凭什么拖垮整个系统?Sentinel 限流熔断实战》
- 《Spring Cloud 微服务实战(四):每个请求都直连服务?你的集群缺一个 Gateway 门卫》
环境与版本说明
跟随本文实战,需要提前准备如下环境:
| 环境 | 版本要求 |
|---|---|
| JDK | 8 或 11(Nacos Server 的运行要求) |
| Nacos Server | 2.5.1 |
| Spring Boot | 2.6.11 |
| Spring Cloud | 2021.0.4 |
| Spring Cloud Alibaba | 2021.0.4.0 |
| 构建工具 | Maven 3.6+ |
| 开发工具 | IntelliJ IDEA(社区版即可) |
提示:Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者的版本存在对应关系,混用版本可能导致启动报错,版本对应关系可查阅 Spring Cloud Alibaba 官方 Wiki。本系列以 Spring Boot 2.x 为基线,暂不涉及 3.x。
一、微服务架构介绍
开始正文之前,默认你已经具备以下基础:
- 掌握 SSM、Spring Boot 的基本使用;
- 熟悉 Maven、Git 的常规操作;
- 本地已安装 JDK 8 或 JDK 11 环境。
1.1 架构演变
软件架构的演进大致经历了三个阶段:单体架构、SOA 架构和微服务架构。
单体架构: 所有功能模块集中在一个工程中开发与部署,即 All in One 模式。

SOA架构: 面向服务的架构,属于单体向微服务过渡的形态。它通常依赖 ESB(企业服务总线)、WebService 等较重的基础设施,在当下的大型项目中已较少采用。
微服务架构: 这一架构风格由 Martin Fowler 提出,官方阐述见:
https://martinfowler.com/articles/microservices.html
其核心定义如下:
In short, the microservice architectural style 1 is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
简而言之,微服务架构风格1是一种将单个应用程序开发为一套小型服务的方法,每个服务都在自己的进程中运行,并与轻量级机制(通常是HTTP资源API)通信。这些服务围绕业务能力构建,并可通过全自动部署机制独立部署。这些服务的集中管理最低限度,这些服务可能用不同的编程语言编写,并使用不同的数据存储技术。
对这段定义做进一步归纳,可以得到微服务架构的几个关键特征:
- 微服务是一种架构风格,而非强制标准;
- 将单体应用按业务能力拆分为多个小型服务,多个服务共同组成完整的产品功能;
- 每个服务可以独立部署,互不影响;
- 服务之间通常采用 HTTP 等轻量级方式进行通信;
- 拆分时一般按业务领域划分边界,也可以将单个独立功能抽象为一个服务;
- 借助 DevOps 实现自动化部署(本系列后续内容会涉及);
- 不同服务可以采用不同的编程语言与技术栈实现。


最后区分三个容易混淆的概念:
- 微服务架构:一种架构思想;
- 微服务:拆分出来的具体服务实例,例如上图中的商品服务;
- 微服务框架:落地微服务架构思想的技术体系,如 Spring Cloud。
1.2 SpringCloud生态
官方地址: https://spring.io/projects/spring-cloud
本系列将围绕 Spring Cloud 生态中的以下组件展开:
- Spring Cloud Alibaba:Nacos(注册中心与配置中心)
- Spring Cloud:OpenFeign(声明式远程调用)
- Spring Cloud Alibaba:Sentinel(限流熔断降级)
- Spring Cloud:Gateway(网关)
- 链路追踪:Sleuth + Zipkin(SkyWalking 本系列不涉及)

说明:本系列聚焦组件的应用与落地,不涉及底层源码分析。
二、Nacos注册中心
2.1 注册中心
考虑这样一个场景:订单服务需要调用库存服务,但它并不知道库存服务的 IP 和端口。如果把库存服务的地址硬编码在订单服务中,会带来明显的耦合问题——库存服务地址变更、集群节点增减时,订单服务都必须跟着修改和维护。
注册中心正是为解决这一问题而生的:每个服务启动时,将自己的基本信息(服务名、IP、端口等)注册到 Nacos;当某个服务需要调用其他服务时,先从 Nacos 查询目标服务的地址信息,再发起调用。这样服务之间的依赖就从"硬编码地址"变成了"按服务名动态发现"。

2.2 Nacos安装
Nacos Server 既可以在 Windows 下本地运行,也可以部署到 Linux 环境,本地开发直接使用官方安装包即可。
需要注意的是,Nacos Server 要求本地 Java 环境为 JDK 8 或 JDK 11(通过 java -version 确认)。

2.5.1 版本下载地址:
https://download.nacos.io/nacos-server/nacos-server-2.5.1.zip
点击即可直接下载(最好去官网下载页获取最新版本)。

打开终端(Windows 下为 cmd)准备启动 Nacos 服务
进入解压后的 bin 目录,执行启动命令(Windows:startup.cmd -m standalone;Linux/Mac:sh startup.sh -m standalone)

启动成功要看到这个日志

启动成功后,浏览器访问 Nacos 提供的图形化控制台:

2.3 Nacos初体验(注册中心)
2.3.1 构建父工程并管理版本
在开始客户端开发之前,先明确一个前提:Spring Cloud 构建在 Spring Boot 之上,而 Spring Boot、Spring Cloud、Spring Cloud Alibaba 三者的版本存在严格的对应关系。
版本对应关系可查阅:
https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E
版本不一致时,部分组件的使用细节会出现差异,建议与本文保持一致。本系列以 Spring Boot 2.x 为基线。
首先构建一个普通的 Maven 父工程,在 pom.xml 中完成四件事:
- 将工程的 packaging 设置为 pom;
- 继承 Spring Boot 的 parent 并指定版本;
- 声明 Spring Cloud 的版本;
- 声明 Spring Cloud Alibaba 的版本。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>
<relativePath />
</parent>
<groupId>com.study</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<spring-cloud.version>2021.0.4</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.3.2 准备库存服务
库存服务(stock)的搭建分为五步:
1、在父工程下创建子工程;
2、引入 Web 与 Nacos 服务发现依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
3、编写启动类,并添加 @EnableDiscoveryClient 注解开启服务注册与发现:
package com.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class StockStarterApp {
public static void main(String[] args) {
SpringApplication.run(StockStarterApp.class, args);
}
}
4、在 application.yml 中配置服务名与 Nacos 地址:
spring:
application:
name: stock
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
5、启动服务,在 Nacos 控制台的服务列表中可以看到 stock 已注册成功:

2.3.3 准备订单服务
订单服务(order)的搭建步骤与库存服务完全一致,仅需调整配置文件:服务名改为 order,并将端口固定为 80。
spring:
application:
name: order
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
server:
port: 80
启动后同样可以在 Nacos 控制台确认注册结果:

2.3.4 库存服务提供接口
在 stock 服务中提供一个对外的测试接口,用于后续验证服务间调用:
package com.study.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StockController {
@GetMapping("/stock/test")
public String test() {
return "stock test!";
}
}
启动后访问 http://localhost:8080/stock/test,确认接口可以正常响应:

2.3.5 订单服务准备接口访问库存服务
首先用最原始的方式实现调用:在启动类中注册 RestTemplate Bean,由 OrderController 直接访问库存服务的固定地址。注意此时地址是硬编码的,尚未接入 Nacos。
package com.study.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class OrderController {
// restTemplate是启动类里构建的!
@Autowired
private RestTemplate restTemplate;
@GetMapping("/order/test")
public String test(){
//1、 直接访问库存服务的/stock/test接口,获取数据
String result = restTemplate.getForObject("http://localhost:8080/stock/test", String.class);
//2、 响应数据
return "Order Test get " + result;
}
}

确认硬编码地址可以正常调用后,下面将其改造为基于 Nacos 的服务名调用。
改造只需两步:给 RestTemplate Bean 追加 @LoadBalanced 注解:
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
然后将调用地址中的 localhost:8080 替换为服务名 stock。

预期效果是 RestTemplate 发起请求时,由 LoadBalancer 将 stock 服务名从 Nacos 解析为具体的 IP 和端口。但实际启动后会发现调用报错:

这是因为在 Spring Cloud 2021.x 版本中,Ribbon 已被移除,负载均衡能力需要显式引入 LoadBalancer 依赖。在 order 服务中补充依赖即可解决:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
再次访问,服务名成功被解析,调用正常返回:

2.4 命名空间和分组(了解)
默认情况下,服务的注册与发现都发生在 Nacos 的 public 命名空间、DEFAULT_GROUP 分组下。实际项目中,通常利用命名空间区分环境(dev/test/prod),利用分组对服务做进一步归类。这两者都可以在 yml 中指定。
先在 Nacos 控制台创建一个新的命名空间,然后让 order 服务连接该命名空间:

此时 stock 服务仍然注册在 public 命名空间下,而 order 服务已改为从 dev 命名空间查找服务,自然找不到 stock,调用随之报错——这正验证了命名空间的隔离效果:

分组的用法类似。将 order 服务的注册与发现分组设置为 PDD_GROUP 后,它只会在该分组内查找服务:

由于 stock 服务注册在 DEFAULT_GROUP 下,order 在 PDD_GROUP 中无法找到它,调用失败,符合预期:

2.5 负载均衡(了解)

需要明确一点:负载均衡并不是 Nacos 本身的职责,而是由客户端侧的 Ribbon 或 LoadBalancer 组件完成的(低版本 Spring Cloud 默认集成 Ribbon,当前版本需要手动引入 LoadBalancer)。
默认采用轮询策略,即请求依次分发到各服务节点,无需额外配置。虽然也支持权重等策略,但实际项目中默认轮询已能满足大多数场景。
为了直观观察轮询效果,对 stock 服务的 test 接口稍作改造,在返回结果中追加当前服务端口:
package com.study.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class StockController {
@Value("${server.port}")
private String serverPort;
@GetMapping("/stock/test")
public String test() {
return "stock test!" + serverPort;
}
}
首次启动时可能遇到占位符解析失败的错误,原因是配置文件中尚未声明 server.port:

补充对应配置后重启即可:

先启动一个 8080 端口的 stock 实例。为了验证集群效果,再通过 IDEA 的启动配置启动第二个 stock 实例(端口 8081)。新版 IDEA 需要先开启"Allow multiple instances"多实例运行选项:

然后在 IDEA 中新增一个启动配置,以 8081 端口启动 stock 服务
两个实例启动成功后,可以在 Nacos 控制台看到 stock 服务下挂载了两个集群节点:
注意:同一集群的多个实例必须使用相同的服务名,服务名不同会被识别为两个独立的服务。

此时反复访问订单接口,返回的端口号会在 8080 与 8081 之间交替出现,即默认的轮询效果:


三、总结
本文完成了微服务实战的第一步,核心收获如下:
- 厘清了微服务架构的核心思想与 Spring Cloud 生态的技术选型。
- 搭建父工程,统一管理 Spring Boot 2.6.11、Spring Cloud 2021.0.4、Spring Cloud Alibaba 2021.0.4.0 三大版本。
- 基于 Nacos 完成订单、库存服务的注册与发现,配合 LoadBalancer 实现按服务名调用。
- 验证了命名空间与分组的隔离效果,以及负载均衡的默认轮询机制。
下一篇预告:使用 Nacos 配置中心集中管理配置文件并实现动态刷新,再用 OpenFeign 优雅地简化跨服务 HTTP 调用。
感兴趣的同学记得 点赞 + 关注,第一时间获取更新通知!
更多推荐

所有评论(0)