Spring Cloud 微服务入门实战教程
一、什么是微服务架构?
1.1 从单体架构说起
传统单体应用将所有功能模块打包在一起部署,例如一个电商系统包含用户、商品、订单、支付等功能,全部写在一个项目中。
单体架构的痛点:
- 代码臃肿,启动慢,维护成本高
- 一个小功能修改需要整个项目重新部署
- 无法针对高并发的模块单独扩容
- 技术栈固定,无法异构
- 团队协作困难,合并代码冲突频繁
1.2 微服务架构定义
微服务架构(Microservices Architecture)是一种将单一应用程序划分为一组小服务的设计模式,每个服务运行在自己的进程中,服务之间通过轻量级通信机制(如 HTTP/REST)协作。
核心特征:
- 单一职责:每个服务只做一件事
- 独立部署:服务可以独立开发、测试、部署
- 去中心化:每个服务可选择最适合的技术栈
- 轻量通信:通常使用 HTTP/REST 或消息队列
- 数据独立:每个服务拥有自己的数据库
二、Spring Cloud 概述
2.1 什么是 Spring Cloud
Spring Cloud 基于 Spring Boot 构建,为微服务架构提供了一站式解决方案,涵盖了服务注册与发现、配置管理、负载均衡、熔断降级、网关路由、分布式追踪等开箱即用的组件。
2.2 版本说明
Spring Cloud 版本以伦敦地铁站命名(按字母顺序):
| Spring Cloud 版本 | 对应的 Spring Boot 版本 |
|---|---|
| Hoxton.SR12 | 2.2.x / 2.3.x |
| 2020.0.x (Ilford) | 2.4.x / 2.5.x |
| 2021.0.x (Jubilee) | 2.6.x / 2.7.x |
| 2022.0.x (Kilburn) | 3.0.x |
| 2023.0.x (Leyton) | 3.2.x |
2.3 核心组件生态
| 组件 | 说明 | 选型(主流) |
|---|---|---|
| 服务注册中心 | 管理所有微服务的地址列表 | Nacos / Eureka / Consul |
| 配置中心 | 统一管理配置文件 | Nacos Config / Apollo |
| 远程调用 | 服务间通信 | OpenFeign + RestTemplate |
| 负载均衡 | 分发请求到多个实例 | Spring Cloud LoadBalancer |
| 网关 | 统一入口,路由转发 | Spring Cloud Gateway |
| 熔断降级 | 防止服务雪崩 | Sentinel / Resilience4j |
| 链路追踪 | 全链路调用监控 | Sleuth + Zipkin / SkyWalking |
三、环境准备
3.1 开发环境
text
JDK 17+
Maven 3.8+
IDE:IntelliJ IDEA
Docker(可选,用于部署中间件)
3.2 创建父工程
创建一个 Maven 项目作为父工程,统一管理依赖版本。
pom.xml:
xml
<?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>
<groupId>com.example</groupId>
<artifactId>cloud-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<java.version>17</java.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-boot.version>3.2.10</spring-boot.version>
<nacos.version>2023.0.1.2</nacos.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<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>${nacos.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
四、服务注册与发现 ------ Nacos
4.1 安装 Nacos
方式一:使用 Docker
bash
docker run -d \
--name nacos \
-p 8848:8848 \
-p 9848:9848 \
-e MODE=standalone \
nacos/nacos-server:v2.3.2
方式二:本地安装
- 从 Nacos 官网 下载安装包
- 解压后执行
bin/startup.cmd -m standalone(Windows) - 访问控制台:http://localhost:8848/nacos,默认用户名密码
nacos/nacos
4.2 创建服务提供者
子模块:cloud-provider
pom.xml:
xml
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.yml:
yaml
server:
port: 8081
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
logging:
level:
com.example: debug
启动类:
java
package com.example.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}
接口:
java
package com.example.provider.controller;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public String getUser(@PathVariable Long id) {
return "用户信息,ID:" + id + ",端口:8081";
}
@GetMapping("/list")
public String listUsers() {
return "用户列表";
}
}
4.3 验证
启动后访问 http://localhost:8848/nacos,在"服务列表"中可以看到 user-service 已注册。
五、远程调用 ------ OpenFeign
OpenFeign 是一个声明式的 HTTP 客户端,让服务间调用像调用本地方法一样简单。
5.1 创建服务消费者
子模块:cloud-consumer
pom.xml:
xml
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
application.yml:
yaml
server:
port: 8082
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
Feign 客户端:
java
package com.example.consumer.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "user-service")
public interface UserFeignClient {
@GetMapping("/users/{id}")
String getUser(@PathVariable("id") Long id);
@GetMapping("/users/list")
String listUsers();
}
启动类:
java
package com.example.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
Controller 调用:
java
package com.example.consumer.controller;
import com.example.consumer.feign.UserFeignClient;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/orders")
public class OrderController {
private final UserFeignClient userFeignClient;
public OrderController(UserFeignClient userFeignClient) {
this.userFeignClient = userFeignClient;
}
@GetMapping("/user/{id}")
public String getUser(@PathVariable Long id) {
return userFeignClient.getUser(id);
}
}
5.2 Feign 核心配置
yaml
spring:
cloud:
openfeign:
client:
config:
default:
connect-timeout: 5000
read-timeout: 5000
logger-level: FULL
compression:
request:
enabled: true
response:
enabled: true
六、负载均衡
Spring Cloud 2020 弃用了 Ribbon,官方推荐使用 Spring Cloud LoadBalancer。
工作流程:
@FeignClient(name = "user-service")声明调用名为user-service的服务- LoadBalancer 从 Nacos 拉取
user-service的实例列表 - 按策略(默认轮询)选择一个实例进行调用
启动两个 provider 实例(不同端口),Feign 会自动负载均衡。
切换负载均衡策略
java
package com.example.consumer.config;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
@Configuration
public class LoadBalancerConfig {
@Bean
public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment,
LoadBalancerClientFactory loadBalancerClientFactory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),
name);
}
}
七、配置中心 ------ Nacos Config
7.1 引入依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
7.2 在 Nacos 创建配置
登录 Nacos 控制台 → "配置管理" → "配置列表" → 点击 "+" 创建配置:
- Data ID:
user-service-dev.yml - Group:
DEFAULT_GROUP - 配置格式: YAML
- 配置内容:
yaml
user:
nickname: 张三
age: 25
7.3 加载配置
bootstrap.yml(注意不是 application.yml):
yaml
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yml
group: DEFAULT_GROUP
profiles:
active: dev
7.4 动态刷新配置
java
package com.example.provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class ConfigController {
@Value("${user.nickname}")
private String nickname;
@Value("${user.age}")
private Integer age;
@GetMapping("/config")
public String getConfig() {
return "nickname:" + nickname + ",age:" + age;
}
}
修改 Nacos 中的配置后,调用 /config 接口即可看到已生效,无需重启服务。
八、网关 ------ Spring Cloud Gateway
8.1 创建网关模块
子模块:cloud-gateway
pom.xml:
xml
<dependencies>
<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>
</dependencies>
application.yml:
yaml
server:
port: 80
spring:
application:
name: gateway-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/users/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/orders/**
discovery:
locator:
enabled: true
lower-case-service-id: true
8.2 启动类
java
package com.example.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
8.3 验证
启动 gateway,访问 http://localhost/users/1 即可路由到 user-service。
九、熔断降级 ------ Sentinel
9.1 安装 Sentinel 控制台
bash
docker run -d \
--name sentinel \
-p 8858:8080 \
bladex/sentinel-dashboard:1.8.8
访问 http://localhost:8858,默认用户名密码 sentinel/sentinel。
9.2 引入依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
9.3 配置 Sentinel
yaml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8858
eager: true
9.4 Feign 整合 Sentinel
yaml
spring:
cloud:
openfeign:
circuitbreaker:
enabled: true
创建 Fallback 工厂:
java
package com.example.consumer.feign.fallback;
import com.example.consumer.feign.UserFeignClient;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class UserFeignFallbackFactory implements FallbackFactory<UserFeignClient> {
@Override
public UserFeignClient create(Throwable cause) {
return new UserFeignClient() {
@Override
public String getUser(Long id) {
return "服务降级:无法获取用户信息," + cause.getMessage();
}
@Override
public String listUsers() {
return "服务降级:无法获取用户列表";
}
};
}
}
修改 Feign 客户端:
java
@FeignClient(name = "user-service", fallbackFactory = UserFeignFallbackFactory.class)
public interface UserFeignClient {
// ...
}
十、链路追踪 ------ Micrometer Tracing
Spring Cloud Sleuth 在 2023.x 版本中被 Micrometer Tracing 替代。
10.1 引入依赖
xml
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
10.2 安装 Zipkin
bash
docker run -d \
--name zipkin \
-p 9411:9411 \
openzipkin/zipkin:latest
10.3 配置
yaml
spring:
application:
name: user-service
logging:
pattern:
level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"
发送请求后,访问 http://localhost:9411 查看链路追踪详情。
十一、项目结构一览
cloud-demo/
├── pom.xml # 父工程,统一版本管理
├── cloud-common/ # 公共模块
│ └── src/main/java/com/example/common
│ ├── result/Result.java # 统一返回结果
│ └── constant/ApiConstant.java # 常量
├── cloud-provider/ # 服务提供者
│ └── src/main/java/com/example/provider
│ ├── ProviderApplication.java
│ ├── controller/UserController.java
│ └── service/UserService.java
├── cloud-consumer/ # 服务消费者
│ └── src/main/java/com/example/consumer
│ ├── ConsumerApplication.java
│ ├── controller/OrderController.java
│ ├── feign/UserFeignClient.java
│ └── feign/fallback/UserFeignFallbackFactory.java
├── cloud-gateway/ # 网关
│ └── src/main/java/com/example/gateway
│ ├── GatewayApplication.java
│ └── config/GatewayConfig.java
└── cloud-auth/ # 认证授权(扩展)
└── src/main/java/com/example/auth
└── AuthApplication.java
十二、配套 SQL(示例)
sql
CREATE DATABASE IF NOT EXISTS cloud_demo DEFAULT CHARSET utf8mb4;
USE cloud_demo;
-- 用户表
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 订单表
CREATE TABLE `order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint NOT NULL COMMENT '用户ID',
`order_no` varchar(32) NOT NULL COMMENT '订单号',
`amount` decimal(10,2) NOT NULL COMMENT '金额',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '0-待支付 1-已支付 2-已取消',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
十三、常见问题
13.1 启动报错 Failed to bind to port
端口被占用,修改 application.yml 中的 server.port,或检查对应端口是否已被其他进程占用。
13.2 Feign 调用报错 LoadBalancer 异常
确认服务名是否注册到 Nacos,FeignClient 中的 name 是否与目标服务的 spring.application.name 一致。
13.3 Nacos 连接失败
确认 Nacos 是否已启动,server-addr 配置是否正确,防火墙是否放行 8848 端口。
13.4 Spring Cloud 版本兼容问题
严格对照版本对应关系,使用 BOM(spring-cloud-dependencies)统一管理版本,避免自行指定子组件版本。
十四、总结
通过本教程,我们完成了一个完整的 Spring Cloud 微服务入门项目:
| 组件 | 功能 |
|---|---|
| Nacos | 服务注册与发现 + 配置中心 |
| OpenFeign | 声明式远程调用 |
| Spring Cloud Gateway | 统一路由网关 |
| Sentinel | 熔断降级与流量控制 |
| Micrometer + Zipkin | 分布式链路追踪 |
微服务不是银弹,引入微服务的同时也带来了网络延迟、数据一致性、运维复杂度等挑战。建议根据实际业务场景合理拆分,不要为了微服务而微服务。