一、微服务与 Spring Cloud 认知
1. 微服务核心概念
- 定义:将单体应用拆分为小型、自治的服务,每个服务聚焦单一业务能力,通过轻量级通信协议(如 HTTP/REST)协同工作。
-
核心特性:
- 单一职责:每个服务对应特定业务领域(如用户服务、订单服务)。
- 自治性:独立开发、测试、部署、扩缩容,不依赖其他服务的部署。
- 松耦合:通过 API 契约通信,内部实现细节对外部透明。
- 技术多样性:不同服务可选择适合自身的技术栈(如 Java、Go、Python)。
2. 微服务解决的问题
-
单体应用痛点:
- 代码臃肿,维护困难;
- 技术栈锁定,难以引入新技术;
- 部署风险高,一个小bug可能导致整个应用崩溃;
- 扩展性差,无法针对热点业务单独扩容。
-
微服务优势:
- 灵活迭代:小团队可快速开发、部署新功能;
- 独立扩容:针对高并发服务单独增加实例;
- 容错性强:单个服务故障不影响整体系统;
- 技术选型灵活:根据业务场景选择最优技术栈。
3. Spring Cloud 定位与价值
- 定义:Spring Cloud 是基于 Spring Boot 的微服务开发工具集,提供了一套完整的微服务架构解决方案。
-
核心价值:
- 简化微服务开发:封装了服务注册发现、配置中心、负载均衡、熔断降级等核心能力;
- 开箱即用:提供了一系列 starter 组件,开发者可快速集成;
- 生态完善:与 Spring Boot 无缝集成,支持各种主流中间件(如 Eureka、Consul、Nacos、RabbitMQ);
- 社区活跃:持续更新迭代,解决实际开发中的问题。
4. Spring Cloud 与 Spring Boot 的关系
- Spring Boot:专注于快速开发单个独立的 Spring 应用,提供自动配置、 starters、嵌入式服务器等特性,简化了 Spring 应用的初始搭建和开发过程。
- Spring Cloud:基于 Spring Boot 构建,用于开发分布式系统中的微服务。它将多个 Spring Boot 应用连接起来,提供了微服务架构所需的各种功能,如服务注册与发现、配置管理、断路器、网关等。
- 关系总结:Spring Boot 是 Spring Cloud 的基础,Spring Cloud 是 Spring Boot 在分布式系统场景下的扩展和应用。一个 Spring Cloud 微服务系统由多个 Spring Boot 应用组成,每个应用都是一个独立的微服务。
二、Spring Cloud 核心组件
1. 服务注册与发现(Eureka/Nacos)
-
核心功能:
- 服务注册:服务启动时,将自身信息(如服务名、IP、端口)注册到注册中心;
- 服务发现:客户端通过服务名从注册中心获取可用服务列表,实现动态调用。
-
Eureka 特性:
- 基于 AP 原则(可用性、分区容错性),适合可用性要求高的场景;
- 自我保护机制:当注册中心丢失部分服务实例时,不会立即剔除,而是保留一段时间,避免误判;
- 客户端缓存:客户端会缓存服务列表,即使注册中心宕机,仍可正常调用已缓存的服务。
-
Nacos 特性:
- 支持 AP 和 CP 模式切换(默认 AP),适配不同场景;
- 除注册发现外,还提供配置中心功能,一站式解决方案;
- 动态配置:支持配置实时更新,无需重启服务;
- 服务健康检查:提供多种健康检查方式(如 HTTP、TCP、MySQL),确保服务可用性。
2. 配置中心(Spring Cloud Config/Nacos)
-
核心功能:
- 集中管理配置:将分散在各个服务的配置(如数据库连接、接口地址)集中存储;
- 动态配置更新:支持配置实时推送,服务无需重启即可生效;
- 环境隔离:为不同环境(开发、测试、生产)提供不同配置。
-
Spring Cloud Config 特性:
- 基于 Git 存储配置,支持版本控制、回滚;
- 客户端拉取配置:服务启动时从 Config Server 拉取配置,默认不支持实时更新(需结合 Spring Cloud Bus 实现);
- 支持加密配置:对敏感配置(如密码)进行加密存储。
-
Nacos Config 特性:
- 支持多种存储方式(本地文件、MySQL、集群);
- 动态更新:配置变更后,实时推送到客户端;
- 配置监听:客户端可监听特定配置项,实现业务逻辑动态调整;
- 支持配置导入/导出,方便批量管理。
3. 负载均衡(Ribbon/OpenFeign)
-
核心功能:
- 客户端负载均衡:客户端从服务列表中选择一个可用服务实例进行调用,避免单点故障;
- 支持多种负载均衡策略:如轮询、随机、权重、响应时间加权等。
-
Ribbon 特性:
- 独立的负载均衡组件,可与 RestTemplate 结合使用;
- 支持自定义负载均衡策略:通过实现
IRule接口扩展; - 服务健康检查:结合 Eureka 可实现基于服务健康状态的负载均衡(只调用健康的服务实例)。
-
OpenFeign 特性:
- 基于接口的声明式调用:通过注解定义接口,自动生成代理类,简化服务调用代码;
- 内置 Ribbon:默认集成 Ribbon 实现负载均衡;
- 支持请求拦截器:可在请求发送前进行拦截处理(如添加认证信息、日志记录);
- 支持 fallback:结合 Hystrix 实现服务降级。
4. 熔断降级(Hystrix/Resilience4j)
-
核心功能:
- 熔断:当服务调用失败率达到阈值时,自动触发熔断,停止调用该服务,避免级联故障;
- 降级:熔断后或服务不可用时,返回预设的 fallback 结果(如默认值、缓存数据),保证系统可用性;
- 限流:限制服务的并发请求数,避免服务因过载而崩溃。
-
Hystrix 特性:
- 基于舱壁模式:将不同服务的调用隔离在不同线程池,避免一个服务故障耗尽所有线程资源;
- 支持熔断、降级、限流、请求缓存等多种功能;
- 监控面板:提供 Hystrix Dashboard 可视化监控服务调用情况。
-
Resilience4j 特性:
- 轻量级:基于 Java 8 开发,无依赖,性能优于 Hystrix;
- 模块化:将熔断、降级、限流等功能拆分为独立模块,可按需引入;
- 支持函数式编程:通过 Lambda 表达式简化配置;
- 监控支持:集成 Micrometer、Prometheus 等监控工具。
5. API 网关(Spring Cloud Gateway)
-
核心功能:
- 路由转发:将客户端请求根据路径、服务名等规则转发到对应的微服务;
- 统一入口:为所有微服务提供统一的访问入口,方便管理和监控;
- 认证授权:对请求进行身份验证和权限校验,防止非法访问;
- 限流熔断:对网关层面的请求进行限流,对下游服务进行熔断降级;
- 日志监控:记录请求日志,方便排查问题。
-
特性:
- 基于 ***ty 开发,异步非阻塞,性能高;
- 支持 WebSocket;
- 路由配置灵活:支持基于配置文件、数据库、动态路由等多种方式;
- 过滤器链:提供丰富的过滤器(如请求头过滤、参数过滤、响应处理),支持自定义过滤器。
6. 服务链路追踪(Sleuth + Zipkin)
-
核心功能:
- 追踪请求链路:记录请求从客户端到各个微服务的调用路径、耗时、状态等信息;
- 问题排查:通过链路追踪快速定位跨服务调用中的问题(如哪个服务调用超时、报错);
- 性能分析:分析各个服务的调用耗时,找出性能瓶颈。
-
Sleuth 特性:
- 轻量级:通过 MDC(Mapped Diagnostic Context)在日志中添加追踪信息(如 traceId、spanId);
- 无侵入:无需修改业务代码,只需引入依赖即可;
- 支持多种采样策略:如全采样、固定比例采样、_rate 采样等。
-
Zipkin 特性:
- 可视化界面:展示请求链路的调用关系、耗时、状态;
- 支持多种存储方式:如内存、MySQL、Elasticsearch;
- 服务依赖分析:展示各个服务之间的调用依赖关系;
- 告警功能:当调用耗时超过阈值或失败率过高时,触发告警。
三、微服务项目初始化
1. 技术选型
- 核心框架:Spring Boot 2.x、Spring Cloud Hoxton/Spring Cloud Alibaba 2021.x
- 注册中心:Nacos(推荐,一站式解决方案)
- 配置中心:Nacos Config
- 负载均衡:OpenFeign(结合 Ribbon)
- 熔断降级:Resilience4j
- API 网关:Spring Cloud Gateway
- 链路追踪:Sleuth + Zipkin
- 数据库:MySQL 8.x
- ORM 框架:MyBatis-Plus
- 消息队列:RabbitMQ(可选,用于异步通信、解耦)
- 部署环境:Docker + Kuber***es(可选,用于容器化部署和编排)
2. 项目结构设计
microservice-demo/
├── microservice-***mon/ # 公共模块(工具类、实体类、常量)
├── microservice-gateway/ # API 网关服务
├── microservice-user/ # 用户服务
├── microservice-order/ # 订单服务
├── microservice-product/ # 商品服务
└── pom.xml # 父工程 pom(统一管理依赖版本)
3. 父工程搭建(Maven)
<!-- pom.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 https://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.13</version> <!-- Spring Boot 版本 -->
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>***.example</groupId>
<artifactId>microservice-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>microservice-demo</name>
<description>Spring Cloud 微服务示例项目</description>
<packaging>pom</packaging> <!-- 父工程打包类型为 pom -->
<!-- 统一管理依赖版本 -->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.5</spring-cloud.version> <!-- Spring Cloud 版本 -->
<spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version> <!-- Spring Cloud Alibaba 版本 -->
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<!-- Spring Cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba 依赖 -->
<dependency>
<groupId>***.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Spring Boot Web 依赖(公共) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
4. 公共模块搭建(microservice-***mon)
- 核心功能:提供跨服务共享的工具类、实体类、常量、异常定义等。
- 依赖配置:
<!-- microservice-***mon/pom.xml -->
<dependencies>
<!-- Lombok 简化实体类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot Validation 数据校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 自定义异常相关 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
</dependencies>
-
示例代码:
- 实体类
UserDTO.java:
- 实体类
package ***.example.***mon.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
public class UserDTO {
private Long id;
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
private String password;
@NotNull(message = "年龄不能为空")
private Integer age;
}
- 自定义异常
BusinessException.java:
package ***.example.***mon.exception;
import lombok.Data;
@Data
public class BusinessException extends RuntimeException {
private Integer code;
private String message;
public BusinessException(Integer code, String message) {
this.code = code;
this.message = message;
}
}
5. 服务模块搭建(以用户服务为例)
- 依赖配置:
<!-- microservice-user/pom.xml -->
<dependencies>
<!-- 公共模块依赖 -->
<dependency>
<groupId>***.example</groupId>
<artifactId>microservice-***mon</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Cloud Nacos 服务发现依赖 -->
<dependency>
<groupId>***.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Spring Cloud Nacos 配置中心依赖 -->
<dependency>
<groupId>***.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- OpenFeign 依赖(用于服务调用) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Resilience4j 熔断降级依赖 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>***.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>***.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
</dependencies>
-
配置文件:
-
bootstrap.yml(优先级高于 application.yml,用于配置中心相关):
-
spring:
application:
name: user-service # 服务名(需与 Nacos 配置中心的配置文件名对应)
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # Nacos 注册中心地址
config:
server-addr: 127.0.0.1:8848 # Nacos 配置中心地址
file-extension: yaml # 配置文件格式
namespace: dev # 环境隔离(开发环境)
-
application.yml(应用自身配置):
server:
port: 8081 # 服务端口
spring:
datasource:
url: jdbc:mysql://localhost:3306/microservice_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: ***.mysql.cj.jdbc.Driver
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # Mapper 映射文件路径
type-aliases-package: ***.example.user.entity # 实体类别名扫描包
configuration:
map-underscore-to-camel-case: true # 下划线转驼峰
# Resilience4j 配置
resilience4j:
circuitbreaker:
instances:
userService: # 熔断实例名(需与 @CircuitBreaker 注解的 name 对应)
slidingWindowSize: 10 # 滑动窗口大小
failureRateThreshold: 50 # 失败率阈值(超过 50% 触发熔断)
waitDurationInOpenState: 10000 # 熔断后等待时间(10 秒后尝试恢复)
retry:
instances:
userService:
maxRetryAttempts: 3 # 最大重试次数
waitDuration: 1000 # 重试间隔(1 秒)
- 启动类:
package ***.example.user;
import org.mybatis.spring.annotation.MapperScan;
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 // 启用服务发现(Spring Cloud 2020 后可省略)
@EnableFeignClients // 启用 OpenFeign
@MapperScan("***.example.user.mapper") // 扫描 Mapper 接口
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
System.out.println("用户服务启动成功!");
}
}
四、核心组件实战
1. 服务注册与发现(Nacos)
-
Nacos 安装与启动:
- 下载 Nacos 安装包(https://github.***/alibaba/nacos/releases);
- 解压后进入
bin目录,执行启动命令:- Windows:
startup.cmd -m standalone(单机模式); - Linux/Mac:
sh startup.sh -m standalone;
- Windows:
- 访问 Nacos 控制台(http://localhost:8848/nacos),默认用户名/密码:nacos/nacos。
-
服务注册:
- 各服务模块引入
spring-cloud-starter-alibaba-nacos-discovery依赖; - 在
bootstrap.yml中配置 Nacos 注册中心地址; - 启动服务后,在 Nacos 控制台的「服务管理 → 服务列表」中可看到注册的服务。
- 各服务模块引入
-
服务发现:
- 通过 OpenFeign 调用其他服务时,直接使用服务名作为 URL 前缀,Nacos 会自动解析为具体的服务实例地址。
2. 配置中心(Nacos Config)
-
Nacos 配置添加:
- 进入 Nacos 控制台,「配置管理 → 配置列表」,点击「+」添加配置;
- 配置信息:
- Data ID:
user-service-dev.yaml(格式:服务名-环境-文件后缀,与 bootstrap.yml 配置对应); - Group:默认
DEFAULT_GROUP; - 配置内容:
- Data ID:
# 数据库配置(可覆盖 application.yml 中的配置)
spring:
datasource:
url: jdbc:mysql://localhost:3306/microservice_user?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
# 自定义配置
user:
name: "张三"
age: 25
-
配置动态更新:
- 在业务类中使用
@Value注解注入配置,结合@RefreshScope实现动态更新:
- 在业务类中使用
package ***.example.user.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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
@RefreshScope // 启用配置动态刷新
public class UserController {
@Value("${user.name}")
private String userName;
@Value("${user.age}")
private Integer userAge;
@GetMapping("/config")
public String getConfig() {
return "用户名:" + userName + ",年龄:" + userAge;
}
}
- 修改 Nacos 中的配置后,无需重启服务,直接访问
/user/config即可看到最新配置。
3. 服务调用(OpenFeign + Ribbon)
- 定义 Feign 接口(用户服务调用商品服务):
package ***.example.user.feign;
import ***.example.***mon.dto.ProductDTO;
import ***.example.user.fallback.ProductFeignFallback;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(
name = "product-service", // 目标服务名(Nacos 中注册的服务名)
fallback = ProductFeignFallback.class // 降级处理类
)
public interface ProductFeignClient {
@GetMapping("/product/{id}")
ProductDTO getProductById(@PathVariable("id") Long id);
}
- 降级处理类:
package ***.example.user.fallback;
import ***.example.***mon.dto.ProductDTO;
import ***.example.user.feign.ProductFeignClient;
import org.springframework.stereotype.***ponent;
@***ponent
public class ProductFeignFallback implements ProductFeignClient {
@Override
public ProductDTO getProductById(Long id) {
// 降级逻辑:返回默认商品信息
ProductDTO productDTO = new ProductDTO();
productDTO.setId(id);
productDTO.setName("默认商品");
productDTO.setPrice(0.0);
return productDTO;
}
}
- 业务调用:
package ***.example.user.service;
import ***.example.***mon.dto.ProductDTO;
import ***.example.user.feign.ProductFeignClient;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private ProductFeignClient productFeignClient;
// 启用熔断降级,指定熔断实例名
@CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
public String getUserInfo(Long userId, Long productId) {
// 调用商品服务
ProductDTO productDTO = productFeignClient.getProductById(productId);
// 模拟获取用户信息
return "用户ID:" + userId + ",购买商品:" + productDTO.getName();
}
// 降级方法(参数和返回值需与原方法一致)
public String getUserFallback(Long userId, Long productId, Exception e) {
return "用户ID:" + userId + ",获取商品信息失败(" + e.getMessage() + "),已启用降级策略";
}
}
4. API 网关(Spring Cloud Gateway)
- 路由配置(application.yml):
spring:
cloud:
gateway:
routes:
# 用户服务路由
- id: user-service-route
uri: lb://user-service # 目标服务名(lb 表示负载均衡)
predicates:
- Path=/user/** # 路径匹配规则
filters:
- RewritePath=/user/(?<path>.*), /$\{path} # 路径重写(去掉 /user 前缀)
- name: RequestRateLimiter # 限流过滤器
args:
redis-rate-limiter.replenishRate: 10 # 令牌桶填充速率(每秒 10 个)
redis-rate-limiter.burstCapacity: 20 # 令牌桶容量(最大 20 个)
# 订单服务路由
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/order/**
filters:
- RewritePath=/order/(?<path>.*), /$\{path}
- 全局过滤器(认证授权示例):
package ***.example.gateway.filter;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import reactor.core.publisher.Mono;
@Configuration
public class GlobalFilterConfig {
@Bean
@Order(-1) // 优先级(数值越小,优先级越高)
public GlobalFilter authFilter() {
return (exchange, chain) -> {
// 获取请求头中的 Token
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token == null || !token.startsWith("Bearer ")) {
// 无 Token 或 Token 格式不正确,返回 401
exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.UNAUTHORIZED);
return exchange.getResponse().set***plete();
}
// 验证 Token(此处简化,实际需调用认证服务)
String realToken = token.substring(7);
if (!"valid_token".equals(realToken)) {
exchange.getResponse().setStatusCode(org.springframework.http.HttpStatus.FORBIDDEN);
return exchange.getResponse().set***plete();
}
// Token 验证通过,继续向下游服务转发
return chain.filter(exchange);
};
}
}
5. 服务链路追踪(Sleuth + Zipkin)
-
Zipkin 安装与启动:
- 下载 Zipkin Jar 包(https://search.maven.org/artifact/io.zipkin/zipkin-server);
- 执行启动命令:
java -jar zipkin-server-2.24.3-exec.jar; - 访问 Zipkin 控制台(http://localhost:9411)。
-
各服务集成 Sleuth + Zipkin:
- 引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
- 配置
application.yml:
spring:
sleuth:
sampler:
probability: 1.0 # 采样率(1.0 表示全采样,生产环境可调整为 0.1)
zipkin:
base-url: http://localhost:9411 # Zipkin 服务器地址
-
链路追踪演示:
- 启动网关、用户服务、商品服务;
- 通过网关访问用户服务的接口(如
http://localhost:8080/user/info?userId=1&productId=1); - 访问 Zipkin 控制台,在「Find Traces」中可看到请求的链路信息,包括调用路径、各服务耗时、状态等。
五、微服务高级特性
1. 服务熔断与降级(Resilience4j 进阶)
-
熔断状态机:
- 关闭状态(Closed):正常接收请求,记录失败率;
- 打开状态(Open):失败率超过阈值,触发熔断,拒绝所有请求;
- 半开状态(Half-Open):熔断后等待一段时间,允许少量请求尝试,若成功则恢复关闭状态,否则继续保持打开状态。
- 限流配置:
resilience4j:
ratelimiter:
instances:
userService:
limitForPeriod: 10 # 每周期最大请求数
limitRefreshPeriod: 1000ms # 周期刷新时间(1 秒)
timeoutDuration: 1000ms # 请求超时时间(1 秒)
- 注解使用:
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
@Service
public class UserService {
// 限流注解
@RateLimiter(name = "userService", fallbackMethod = "getUserRateLimitFallback")
public String getUserInfoByRateLimit(Long userId) {
return "用户ID:" + userId + ",请求成功";
}
// 限流降级方法
public String getUserRateLimitFallback(Long userId, Exception e) {
return "用户ID:" + userId + ",请求过于频繁,请稍后再试";
}
}
2. 分布式事务(Seata)
-
核心概念:
- 事务协调器(TC):协调全局事务的提交或回滚;
- 事务管理器(TM):发起全局事务,定义事务的范围;
- 资源管理器(RM):管理本地事务资源,参与全局事务的提交或回滚。
-
Seata 安装与配置:
- 下载 Seata 安装包(https://github.***/seata/seata/releases);
- 解压后修改
conf/registry.conf,配置 Nacos 作为注册中心和配置中心; - 启动 Seata Server:
bin/seata-server.sh(Linux/Mac)或bin/seata-server.bat(Windows)。
-
项目集成 Seata:
- 引入依赖:
<dependency>
<groupId>***.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
- 配置
application.yml:
seata:
application-id: ${spring.application.name}
tx-service-group: my_test_tx_group # 事务组名称(需与 Seata Server 配置一致)
registry:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
-
分布式事务示例(AT 模式):
- 订单服务(TM):
package ***.example.order.service;
import ***.alibaba.fastjson.JSON;
import ***.example.***mon.dto.OrderDTO;
import ***.example.order.entity.Order;
import ***.example.order.mapper.OrderMapper;
import ***.example.order.feign.UserFeignClient;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserFeignClient userFeignClient;
// 全局事务注解
@GlobalTransactional(rollbackFor = Exception.class)
public void createOrder(OrderDTO orderDTO) {
// 1. 创建订单(本地事务)
Order order = new Order();
order.setUserId(orderDTO.getUserId());
order.setProductId(orderDTO.getProductId());
order.setAmount(orderDTO.getAmount());
orderMapper.insert(order);
// 2. 调用用户服务扣减余额(远程事务)
boolean deductSu***ess = userFeignClient.deductBalance(orderDTO.getUserId(), orderDTO.getAmount());
if (!deductSu***ess) {
// 扣减失败,触发全局事务回滚
throw new RuntimeException("用户余额不足,创建订单失败");
}
// 3. 模拟异常(测试回滚)
// int i = 1 / 0;
}
}
- 用户服务(RM):
package ***.example.user.service;
import ***.example.user.entity.User;
import ***.example.user.mapper.UserMapper;
import io.seata.core.context.RootContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 本地事务注解(需与 Seata 集成)
@Transactional
public boolean deductBalance(Long userId, Double amount) {
// 验证全局事务是否存在
if (RootContext.getXID() == null) {
throw new RuntimeException("未检测到全局事务");
}
User user = userMapper.selectById(userId);
if (user == null) {
throw new RuntimeException("用户不存在");
}
if (user.getBalance() < amount) {
return false;
}
// 扣减余额
user.setBalance(user.getBalance() - amount);
userMapper.updateById(user);
return true;
}
}
3. 服务监控(Spring Boot Admin)
-
Spring Boot Admin 服务端搭建:
- 依赖配置:
<dependencies>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-server</artifactId>
<version>2.6.10</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-***flix-eureka-client</artifactId>
</dependency>
</dependencies>
- 启动类:
package ***.example.admin;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableAdminServer // 启用 Spring Boot Admin 服务端
@EnableDiscoveryClient
public class AdminServerApplication {
public static void main(String[] args) {
SpringApplication.run(AdminServerApplication.class, args);
}
}
-
客户端集成:
- 各服务引入依赖:
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>2.6.10</version>
</dependency>
- 配置
application.yml:
spring:
boot:
admin:
client:
url: http://localhost:8088 # Spring Boot Admin 服务端地址
username: admin # 服务端认证用户名(若配置)
password: admin123 # 服务端认证密码(若配置)
management:
endpoints:
web:
exposure:
include: "*" # 暴露所有监控端点
endpoint:
health:
show-details: always # 显示健康详情
-
监控功能:
- 访问 Spring Boot Admin 控制台(http://localhost:8088),可查看各服务的健康状态、内存使用、CPU 占用、日志、接口调用情况等。
六、微服务部署与运维
1. Docker 容器化部署
- 服务 Dockerfile 示例(用户服务):
# 基础镜像(Java 8)
FROM openjdk:8-jdk-alpine
# 维护者信息
LABEL maintainer="example@163.***"
# 暴露端口
EXPOSE 8081
# 添加 JAR 包
ADD target/microservice-user-0.0.1-SNAPSHOT.jar user-service.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/user-service.jar"]
- 构建 Docker 镜像:
# 进入服务模块目录
cd microservice-user
# 构建 JAR 包
mvn clean package -Dmaven.test.skip=true
# 构建 Docker 镜像
docker build -t user-service:1.0 .
- 运行 Docker 容器:
docker run -d -p 8081:8081 --name user-service \
--link nacos:nacos \
--link zipkin:zipkin \
-e SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR=nacos:8848 \
-e SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR=nacos:8848 \
-e SPRING_ZIPKIN_BASE-URL=http://zipkin:9411 \
user-service:1.0
2. Kuber***es 编排部署
- Deployment 配置示例(user-service-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: microservice
spec:
replicas: 2 # 副本数
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:1.0
ports:
- containerPort: 8081
env:
- name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR
value: "nacos-service:8848"
- name: SPRING_CLOUD_NACOS_CONFIG_SERVER-ADDR
value: "nacos-service:8848"
- name: SPRING_ZIPKIN_BASE-URL
value: "http://zipkin-service:9411"
resources:
limits:
memory: "1Gi"
cpu: "500m"
requests:
memory: "512Mi"
cpu: "200m"
livenessProbe: # 存活探针
httpGet:
path: /actuator/health
port: 8081
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe: # 就绪探针
httpGet:
path: /actuator/health
port: 8081
initialDelaySeconds: 30
periodSeconds: 5
- Service 配置示例(user-service-service.yaml):
apiVersion: v1
kind: Service
metadata:
name: user-service
namespace: microservice
spec:
selector:
app: user-service
ports:
- port: 8081
targetPort: 8081
type: ClusterIP # 集群内部访问(若需外部访问,可改为 NodePort 或 LoadBalancer)
- 部署命令:
# 创建命名空间
kubectl create namespace microservice
# 部署 Deployment
kubectl apply -f user-service-deployment.yaml -n microservice
# 部署 Service
kubectl apply -f user-service-service.yaml -n microservice
# 查看部署状态
kubectl get pods -n microservice
kubectl get svc -n microservice
3. 日志收集(ELK)
-
核心组件:
- Elasticsearch:存储日志数据;
- Logstash:收集、过滤、转换日志数据,发送到 Elasticsearch;
- Kibana:可视化展示日志数据,支持查询、分析。
-
Spring Boot 服务集成 Logback 输出 JSON 日志:
- 引入依赖:
<dependency>
<groupId>***.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>7.2.0</version>
</dependency>
- 配置
logback-spring.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!-- 输出 JSON 格式日志 -->
<appender name="JSON_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/${spring.application.name}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/${spring.application.name}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder class="***.logstash.logback.encoder.LogstashEncoder">
<includeMdcKeyName>traceId</includeMdcKeyName>
<includeMdcKeyName>spanId</includeMdcKeyName>
<includeMdcKeyName>userId</includeMdcKeyName>
<customFields>{"service":"${spring.application.name}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="JSON_FILE"/>
</root>
</configuration>
- Logstash 配置(logstash.conf):
input {
file {
path => "/var/log/microservice/*.log" # 日志文件路径(Docker/K8s 挂载的日志目录)
start_position => "beginning"
sincedb_path => "/dev/null"
codec => "json"
}
}
filter {
if [service] == "user-service" {
mutate {
add_field => { "[@metadata][index_prefix]" => "user-service" }
}
} else if [service] == "order-service" {
mutate {
add_field => { "[@metadata][index_prefix]" => "order-service" }
}
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"] # Elasticsearch 地址
index => "%{[@metadata][index_prefix]}-%{+YYYY.MM.dd}" # 索引名(按服务和日期拆分)
}
stdout { codec => rubydebug }
}
七、总结与展望
1. 微服务实践总结
- 核心优势:微服务架构通过拆分业务、独立部署、灵活扩展,解决了单体应用的臃肿、僵化、难以维护等问题,适合复杂业务系统的开发与演进。
-
关键挑战:
- 分布式系统的复杂性:服务间依赖、分布式事务、数据一致性等问题需重点解决;
- 运维成本提升:微服务数量多,部署、监控、排查问题的难度增加;
- 团队协作要求高:需明确服务边界、接口契约,避免重复开发。
-
实践建议:
- 合理拆分服务:基于业务领域边界拆分,避免过度拆分(如一个小功能拆分为多个服务);
- 优先解决核心问题:如服务注册发现、配置中心、熔断降级等基础能力,再逐步引入分布式事务、监控等高级特性;
- 自动化运维:借助 Docker、K8s、CI/CD 工具,实现部署、扩容、回滚的自动化,降低运维成本。
2. 微服务未来趋势
- 云原生架构:微服务与云原生技术(如容器化、服务网格、Serverless)深度融合,实现更高效的资源利用、更灵活的弹性伸缩;
- 服务网格(Istio):将服务间的通信、流量控制、安全认证等功能从业务代码中剥离,由服务网格统一管理,简化微服务开发;
- 低代码/无代码平台:结合微服务架构,提供可视化开发、拖拽式配置,降低微服务的开发门槛;
- AI 驱动的运维:通过 AI 技术实现日志分析、故障预测、智能扩容,提升微服务系统的稳定性和运维效率。
微服务架构不是银弹,需结合业务场景和团队能力合理选择。在实践过程中,应持续优化服务设计、完善技术体系,逐步构建稳定、高效、可扩展的微服务系统。