本文将基于最新稳定版本构建完整微服务体系:
选择理由:Spring Cloud 2023.0.x是目前最新的稳定版本系列,全面支持Spring Boot 3.2.x,移除了大量过时组件,采用Resilience4j作为官方推荐的熔断方案,更符合现代微服务架构需求。
服务注册中心是微服务架构的核心基础设施,负责服务地址的管理。
步骤1:创建Maven项目,添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
</parent>
<dependencies>
<!-- Eureka Server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!-- actuator用于监控 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2023.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
步骤2:创建启动类,添加@EnableEurekaServer注解
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer // 启用Eureka服务注册中心功能
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
步骤3:配置application.yml
server:
port: 8761 # Eureka默认端口
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 自身不注册到注册中心
fetch-registry: false # 不需要从注册中心获取服务信息
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
enable-self-preservation: false # 关闭自我保护模式(生产环境建议开启)
eviction-interval-timer-in-ms: 30000 # 清理无效节点的间隔时间
启动验证:访问 http://localhost:8761 可看到Eureka控制台界面,此时还没有服务注册。
我们创建一个简单的商品服务(product-service)作为服务提供者。
步骤1:添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
步骤2:创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient // 启用服务发现客户端功能
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
步骤3:配置application.yml
server:
port: 8081
spring:
application:
name: product-service # 服务名称,消费者将通过此名称调用
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true # 注册时使用IP地址
instance-id: ${spring.cloud.client.ip-address}:${server.port} # 显示IP和端口
步骤4:创建业务接口
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/products")
public class ProductController {
// 模拟数据库存储
private static final Map<Long, Product> productMap = new HashMap<>();
static {
productMap.put(1L, new Product(1L, "Spring Boot实战", 59.9));
productMap.put(2L, new Product(2L, "Spring Cloud微服务", 69.9));
}
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
// 模拟服务调用延迟
try {
Thread.sleep(500);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Product product = productMap.get(id);
if (product == null) {
throw new RuntimeException("产品不存在");
}
return product;
}
@PostMapping
public Product createProduct(@RequestBody Product product) {
productMap.put(product.getId(), product);
return product;
}
// 内部静态类
public static class Product {
private Long id;
private String name;
private Double price;
// 构造函数、getter和setter省略
public Product() {}
public Product(Long id, String name, Double price) {
this.id = id;
this.name = name;
this.price = price;
}
// getter和setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
}
}
启动验证:启动服务后,访问Eureka控制台(http://localhost:8761),可看到PRODUCT-SERVICE已注册。
创建订单服务(order-service)作为服务消费者,通过OpenFeign调用商品服务。
步骤1:添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 熔断依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
步骤2:创建启动类
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 // 启用Feign客户端
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
步骤3:配置application.yml
server:
port: 8082
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
# Resilience4j配置
resilience4j:
circuitbreaker:
instances:
productService:
sliding-window-size: 10
failure-rate-threshold: 50
wait-duration-in-open-state: 10000
permitted-number-of-calls-in-half-open-state: 3
retry:
instances:
productService:
max-retry-attempts: 3
wait-duration: 1000
步骤4:创建Feign客户端
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
// 指定要调用的服务名称
@FeignClient(name = "product-service")
public interface ProductFeignClient {
@GetMapping("/products/{id}")
Product getProduct(@PathVariable("id") Long id);
// 产品实体类,与服务提供者保持一致
class Product {
private Long id;
private String name;
private Double price;
// getter和setter省略
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
}
}
步骤5:创建服务和控制器
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private ProductFeignClient productFeignClient;
// 使用熔断和重试机制
@GetMapping("/{productId}")
@CircuitBreaker(name = "productService", fallbackMethod = "getOrderFallback")
@Retry(name = "productService")
public Order getOrder(@PathVariable Long productId) {
ProductFeignClient.Product product = productFeignClient.getProduct(productId);
return new Order(System.currentTimeMillis(), productId, product.getName(), 1, product.getPrice());
}
// 熔断降级方法
public Order getOrderFallback(Long productId, Exception e) {
return new Order(System.currentTimeMillis(), productId, "降级商品", 1, 0.0);
}
// 订单实体类
public static class Order {
private Long id;
private Long productId;
private String productName;
private Integer quantity;
private Double price;
// 构造函数、getter和setter省略
public Order(Long id, Long productId, String productName, Integer quantity, Double price) {
this.id = id;
this.productId = productId;
this.productName = productName;
this.quantity = quantity;
this.price = price;
}
// getter和setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getProductId() { return productId; }
public void setProductId(Long productId) { this.productId = productId; }
public String getProductName() { return productName; }
public void setProductName(String productName) { this.productName = productName; }
public Integer getQuantity() { return quantity; }
public void setQuantity(Integer quantity) { this.quantity = quantity; }
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
}
}
验证服务调用:
API网关作为微服务的入口,负责路由转发、负载均衡、认证授权等功能。
步骤1:创建网关项目,添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
注意:Spring Cloud Gateway基于Netty和WebFlux,不能与spring-boot-starter-web(Servlet)同时使用,会导致冲突。
步骤2:创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
步骤3:配置application.yml
server:
port: 8080 # 网关端口
spring:
application:
name: api-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 启用服务发现定位器
lower-case-service-id: true # 服务ID转为小写
routes:
- id: product-service
uri: lb://product-service # 负载均衡到product-service
predicates:
- Path=/api/products/** # 匹配路径
filters:
- StripPrefix=1 # 去除路径前缀/api
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 令牌桶填充速率
redis-rate-limiter.burstCapacity: 20 # 令牌桶容量
key-resolver: "#{@ipAddressKeyResolver}" # 基于IP的限流
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
instance:
prefer-ip-address: true
步骤4:配置限流策略
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class GatewayConfig {
// 基于IP地址的限流
@Bean
public KeyResolver ipAddressKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest()
.getRemoteAddress()
.getAddress()
.getHostAddress()
);
}
}
验证网关功能:
通过本文的实操指南,你已掌握基于最新Spring Boot和Spring Cloud构建微服务架构的核心技能。在实际项目中,可根据业务需求进行扩展和优化,构建稳定、高效、可扩展的微服务系统。
Spring Boot 3.2,Spring Cloud 2023.0, 微服务架构,实操指南,企业级分布式系统,系统搭建,完整方案,Spring 集成,微服务开发,分布式架构,企业级应用,Spring 框架,微服务实践,分布式系统构建,Java 微服务
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。