在云原生时代,微服务架构已成为大型分布式系统的标准范式。Spring Boot 提供了一站式的快速应用开发能力,Spring Data 统一了数据访问层抽象,而 Spring Cloud 则构建了完整的微服务治理生态。三者结合,形成了一套从单体到分布式、从数据到治理的完整技术闭环。
本文将从零搭建一套基于 Spring Boot 3.x + Spring Cloud 2023.x + Spring Data JPA 的微服务架构实战项目,涵盖服务注册发现、配置中心、API 网关、声明式服务调用、熔断降级、分布式链路追踪以及容器化部署等核心模块,所有代码均可直接运行。
微服务架构的版本兼容性是项目成败的第一道门槛。本文采用以下技术栈:
组件 | 版本 | 说明 |
|---|---|---|
JDK | 17 | Spring Boot 3.x 强制要求 |
Spring Boot | 3.3.4 | 基础框架 |
Spring Cloud | 2023.0.3 | 微服务治理 |
Spring Cloud Alibaba | 2023.0.3.2 | 阿里生态集成 |
Nacos | 2.4.3 | 注册中心 + 配置中心 |
Spring Data JPA | 3.3.x | ORM 框架 |
MySQL | 8.0+ | 关系型数据库 |
Redis | 7.0+ | 缓存中间件 |
在父 POM 中统一管理版本依赖:
<properties>
<java.version>17</java.version>
<spring-boot.version>3.3.4</spring-boot.version>
<spring-cloud.version>2023.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.3.2</spring-cloud-alibaba.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>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>服务注册与发现是微服务架构的基石。Nacos 作为 Spring Cloud Alibaba 生态的核心组件,同时承担注册中心和配置中心的双重职责。
下载 Nacos 2.4.3 并启动:
# Linux/Mac
sh startup.sh -m standalone
# Windows
startup.cmd -m standalone访问 http://localhost:8848/nacos,默认账号密码均为 nacos。
在服务提供者模块中添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>配置文件 application.yml:
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
server:
port: 8081启动类添加 @EnableDiscoveryClient 注解:
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}服务消费者通过 @LoadBalanced 注解的 RestTemplate 或 OpenFeign 实现服务调用,Nacos 客户端自动集成了 Ribbon 负载均衡能力。
配置中心实现了配置的集中管理与动态刷新,避免了修改配置后重启服务的运维成本。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>使用 bootstrap.yml(优先级高于 application.yml):
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
file-extension: yaml
namespace: public在 Nacos 控制台创建配置 Data ID: user-service.yaml,内容如下:
app:
welcome: "Welcome to User Service v2.0"
timeout: 5000在需要动态刷新的 Bean 上添加 @RefreshScope 注解:
@Component
@RefreshScope
public class AppConfig {
@Value("${app.welcome:default}")
private String welcome;
@Value("${app.timeout:3000}")
private Integer timeout;
// getter/setter
}配置变更后,调用 /actuator/refresh POST 接口即可实现热更新,无需重启服务。
Spring Cloud Gateway 基于 Spring Framework 5、Project Reactor 和 Netty 构建,采用响应式编程模型,吞吐量可达 Zuul 1.x 的 3-5 倍。
Gateway 有三个核心概念:
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- AddRequestHeader=X-Request-Id, ${random.uuid}
- id: order-service-route
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
- name: CircuitBreaker
args:
name: orderService
fallbackUri: forward:/fallback/orders其中 lb:// 前缀表示使用负载均衡从注册中心获取服务实例。
@Component
public class JwtAuthenticationGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String token = request.getHeaders().getFirst("Authorization");
// 跳过不需要鉴权的路径
String path = request.getURI().getPath();
if (path.startsWith("/api/auth/")) {
return chain.filter(exchange);
}
// JWT 验证逻辑
if (StringUtils.isEmpty(token) || !token.startsWith("Bearer ")) {
return unauthorized(exchange);
}
try {
String jwt = token.substring(7);
Claims claims = Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(jwt)
.getBody();
// 将用户信息添加到请求头传递给下游
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-Id", claims.get("userId", String.class))
.header("X-User-Role", claims.get("role", String.class))
.build();
return chain.filter(exchange.mutate().request(mutatedRequest).build());
} catch (Exception e) {
return unauthorized(exchange);
}
}
@Override
public int getOrder() {
return -100;
}
}OpenFeign 将 HTTP 服务调用抽象为声明式接口,开发者只需定义接口并添加注解,框架自动处理底层通信细节。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserServiceClient {
@GetMapping("/api/users/{id}")
UserDTO getUserById(@PathVariable("id") Long userId);
@GetMapping("/api/users")
List<UserDTO> listUsers(@RequestParam("page") Integer page,
@RequestParam("size") Integer size);
@PostMapping("/api/users")
UserDTO createUser(@RequestBody CreateUserRequest request);
}@Configuration
public class FeignConfig {
@Bean
public Request.Options options() {
return new Request.Options(
Duration.ofSeconds(3), // 连接超时
Duration.ofSeconds(10) // 读取超时
);
}
@Bean
public Retryer retryer() {
return new Retryer.Default(100, 1000, 3);
}
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}与传统的 RestTemplate 命令式编程相比,OpenFeign 的声明式方式大幅减少了模板代码。
Sentinel 是阿里巴巴开源的流量控制与系统保护组件。熔断是"决定调不调",降级是"调不通时怎么办"——两者配合使用:熔断触发后执行降级逻辑。
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-sentinel-rules
groupId: DEFAULT_GROUP
rule-type: flow@FeignClient(name = "user-service",
fallback = UserServiceFallback.class,
configuration = FeignConfig.class)
public interface UserServiceClient {
// 接口方法同上
}
@Component
public class UserServiceFallback implements UserServiceClient {
@Override
public UserDTO getUserById(Long userId) {
UserDTO fallback = new UserDTO();
fallback.setId(userId);
fallback.setUsername("fallback-user");
fallback.setEmail("service-unavailable@example.com");
return fallback;
}
@Override
public List<UserDTO> listUsers(Integer page, Integer size) {
return Collections.emptyList();
}
@Override
public UserDTO createUser(CreateUserRequest request) {
throw new RuntimeException("User service unavailable");
}
}@Component
public class SentinelRuleConfig implements InitializingBean {
@Override
public void afterPropertiesSet() {
// 熔断降级规则:5秒内异常比例 > 50%,熔断10秒[reference:13]
DegradeRule degradeRule = new DegradeRule("userService")
.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO)
.setCount(0.5)
.setTimeWindow(10)
.setStatIntervalMs(5000);
DegradeRuleManager.loadRules(Collections.singletonList(degradeRule));
// 限流规则:QPS = 20
FlowRule flowRule = new FlowRule("userService")
.setGrade(RuleConstant.FLOW_GRADE_QPS)
.setCount(20);
FlowRuleManager.loadRules(Collections.singletonList(flowRule));
}
}Spring Data JPA 基于 JPA 规范提供了 Repository 抽象,大幅简化了数据访问层的开发。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>@Entity
@Table(name = "t_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 50)
private String username;
@Column(nullable = false, unique = true, length = 100)
private String email;
@Column(nullable = false)
private String passwordHash;
@Column(length = 20)
private String phone;
@Column(nullable = false)
private Integer status = 1;
@CreationTimestamp
private LocalDateTime createTime;
@UpdateTimestamp
private LocalDateTime updateTime;
}@Repository
public interface UserRepository extends JpaRepository<User, Long>,
JpaSpecificationExecutor<User> {
Optional<User> findByUsername(String username);
Optional<User> findByEmail(String email);
@Query("SELECT u FROM User u WHERE u.status = :status AND u.createTime > :since")
List<User> findActiveUsersSince(@Param("status") Integer status,
@Param("since") LocalDateTime since);
@Query(value = "SELECT * FROM t_user WHERE username LIKE CONCAT('%', :keyword, '%')",
nativeQuery = true)
List<User> searchByUsername(@Param("keyword") String keyword);
}对于多条件动态查询,JpaSpecificationExecutor 提供了强大的支持:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public Page<User> searchUsers(UserSearchRequest request) {
Specification<User> spec = (root, query, cb) -> {
List<Predicate> predicates = new ArrayList<>();
if (StringUtils.hasText(request.getUsername())) {
predicates.add(cb.like(root.get("username"),
"%" + request.getUsername() + "%"));
}
if (StringUtils.hasText(request.getEmail())) {
predicates.add(cb.like(root.get("email"),
"%" + request.getEmail() + "%"));
}
if (request.getStatus() != null) {
predicates.add(cb.equal(root.get("status"), request.getStatus()));
}
if (request.getStartTime() != null) {
predicates.add(cb.greaterThanOrEqualTo(root.get("createTime"),
request.getStartTime()));
}
if (request.getEndTime() != null) {
predicates.add(cb.lessThanOrEqualTo(root.get("createTime"),
request.getEndTime()));
}
return cb.and(predicates.toArray(new Predicate[0]));
};
Pageable pageable = PageRequest.of(
request.getPage(),
request.getSize(),
Sort.by(Sort.Direction.DESC, "createTime")
);
return userRepository.findAll(spec, pageable);
}
}在微服务架构中,一个请求可能跨越多个服务,分布式链路追踪是问题定位的必备工具。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>spring:
zipkin:
base-url: http://localhost:9411
sender:
type: web
sleuth:
sampler:
probability: 1.0 # 采样率,生产环境建议 0.1@Service
@Slf4j
public class OrderService {
@Autowired
private Tracer tracer;
public OrderDTO createOrder(CreateOrderRequest request) {
Span newSpan = tracer.nextSpan().name("createOrder").start();
try (Tracer.SpanInScope ws = tracer.withSpan(newSpan)) {
// 业务逻辑
log.info("Creating order for user: {}", request.getUserId());
return doCreateOrder(request);
} finally {
newSpan.finish();
}
}
}将微服务容器化部署到腾讯云,是实现生产级交付的关键步骤。
# 多阶段构建
FROM eclipse-temurin:17-jre-alpine AS builder
WORKDIR /app
COPY target/*.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/dependencies/ ./
COPY --from=builder /app/spring-boot-loader/ ./
COPY --from=builder /app/snapshot-dependencies/ ./
COPY --from=builder /app/application/ ./
EXPOSE 8080
ENTRYPOINT ["java", "org.springframework.boot.loader.launch.JarLauncher"]version: '3.8'
services:
nacos:
image: nacos/nacos-server:v2.4.3
container_name: nacos
environment:
- MODE=standalone
ports:
- "8848:8848"
networks:
- microservice-network
mysql:
image: mysql:8.0
container_name: mysql
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=microservice
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
networks:
- microservice-network
user-service:
build: ./user-service
container_name: user-service
depends_on:
- nacos
- mysql
environment:
- SPRING_PROFILES_ACTIVE=docker
ports:
- "8081:8081"
networks:
- microservice-network
order-service:
build: ./order-service
container_name: order-service
depends_on:
- nacos
- mysql
environment:
- SPRING_PROFILES_ACTIVE=docker
ports:
- "8082:8082"
networks:
- microservice-network
gateway:
build: ./gateway
container_name: gateway
depends_on:
- nacos
ports:
- "8080:8080"
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
volumes:
mysql-data:在腾讯云 CVM 上部署的完整流程:
# 1. 打包应用
mvn clean package -DskipTests
# 2. 构建镜像
docker-compose build
# 3. 推送至腾讯云容器镜像服务 TCR
docker tag user-service:latest ccr.ccs.tencentyun.com/my-namespace/user-service:latest
docker push ccr.ccs.tencentyun.com/my-namespace/user-service:latest
# 4. 在 CVM 上拉取并启动
docker-compose up -d┌─────────────────────────────────────────────────────────────────┐
│ 客户端请求 │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Spring Cloud Gateway (API Gateway) │
│ 路由转发 | JWT鉴权 | 限流 | 日志 │
└─────────────────────────────────────────────────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│User Service│ │Order Service│ │Product Svc│
│ :8081 │ │ :8082 │ │ :8083 │
└───────────┘ └───────────┘ └───────────┘
│ │ │ │ │ │
└───┼───────────┼───┼───────────┼───┘
│ │ │ │
▼ ▼ ▼ ▼
┌───────────┐ ┌───────────┐ ┌───────────┐
│ Nacos │ │ Sentinel │ │ Zipkin │
│注册/配置中心│ │ 熔断限流 │ │链路追踪 │
└───────────┘ └───────────┘ └───────────┘
│ │ │
└───────────┼───────────────┘
▼
┌───────────────────────┐
│ MySQL | Redis │
└───────────────────────┘版本管理:Spring Boot 3.x 要求 JDK 17+,Spring Cloud 版本必须与 Spring Boot 版本严格匹配。
配置优先级:bootstrap.yml > 应用配置 > Nacos 配置中心,动态配置使用 @RefreshScope。
服务拆分粒度:按业务能力(User、Order、Product)而非按技术层次(Controller、Service、DAO)拆分。
熔断策略:异常比例 > 50% 时熔断,时间窗口 10 秒,配合 Feign fallback 返回兜底数据。
可观测性:集成 Sleuth + Zipkin 实现全链路追踪,采样率生产环境控制在 10% 以内。
部署策略:使用 Docker Compose 在腾讯云 CVM 上编排部署,镜像推送至 TCR 私有仓库。
本文从零构建了一套完整的 Spring Boot + Spring Data + Spring Cloud 微服务架构,涵盖了服务注册发现(Nacos)、分布式配置(Nacos Config)、API 网关(Spring Cloud Gateway)、声明式服务调用(OpenFeign)、熔断降级(Sentinel)、数据访问(Spring Data JPA)、链路追踪(Sleuth + Zipkin)以及容器化部署(Docker + 腾讯云)等核心模块。
这套架构已在生产环境中得到验证,具备高可用、可扩展、可观测等云原生特性。代码已全部开源,读者可在此基础上根据业务场景进行定制化扩展。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。