微服务架构是一种将应用程序构建为一组小型、自治服务的方法,每个服务运行在自己的进程中,并通过轻量级机制(通常是HTTP RESTful API或消息队列)进行通信。
核心思想: 将单一的大型应用程序拆分成多个小型服务,每个服务专注于特定的业务功能,可以独立开发、部署和扩展。
| 特性 | 单体架构 | 微服务架构 |
|---|---|---|
| 代码结构 | 单一代码库 | 多个独立代码库 |
| 部署方式 | 整体部署 | 独立部署 |
| 扩展能力 | 整体扩展 | 按需扩展单个服务 |
| 技术栈 | 统一技术栈 | 可使用不同技术 |
| 开发团队 | 大团队协作 | 小团队独立开发 |
| 故障影响 | 整体不可用 | 局部故障隔离 |
| 开发复杂度 | 初期简单 | 初期复杂 |
| 运维复杂度 | 部署简单 | 需要完善基础设施 |
微服务引入了分布式系统的所有复杂性:网络延迟、分布式事务、服务间通信、数据一致性、运维复杂度。如果团队规模小、业务领域不清晰、基础设施不完善,单体架构可能是更好的选择。微服务是演进而来的,不是一开始就设计出来的。
| 组件 | Netflix 体系(维护模式) | Alibaba 体系(推荐) |
|---|---|---|
| 注册中心 | Eureka | Nacos |
| 配置中心 | Spring Cloud Config | Nacos Config |
| 网关 | Zuul | Spring Cloud Gateway |
| 熔断器 | Hystrix | Sentinel |
| 负载均衡 | Ribbon | Spring Cloud LoadBalancer |
| 分布式事务 | — | Seata |
新项目推荐使用 Spring Cloud Alibaba 体系,社区活跃且与国内基础设施(如 Dubbo、RocketMQ)生态更契合。
这是最常用的拆分方式,基于业务领域划分服务边界。
示例:电商系统拆分
电商系统
├── 用户服务(User Service) - 用户注册、认证、个人信息管理
├── 商品服务(Product Service) - 商品管理、分类、库存
├── 订单服务(Order Service) - 订单创建、状态管理
├── 支付服务(Payment Service) - 支付处理、退款
├── 物流服务(Shipping Service) - 物流跟踪、配送管理
└── 通知服务(Notification Service) - 短信、邮件通知基于领域驱动设计(DDD)的思想,识别核心域、支撑域和通用域。
核心域: 订单、商品、支付(业务核心竞争力)
支撑域: 用户管理、权限管理(支撑核心业务)
通用域: 通知服务、文件服务(通用功能)不要过度拆分,遵循"先粗后细"的原则:
判断标准:
每个服务独享数据库(Database per Service):
用户服务 → 用户数据库(MySQL)
商品服务 → 商品数据库(PostgreSQL)
订单服务 → 订单数据库(MongoDB)优点:
挑战:
Spring Cloud 是一套完整的微服务解决方案,提供了构建分布式系统所需的常见模式。
| 组件类别 | Spring Cloud 组件 | 功能说明 |
|---|---|---|
| 服务注册与发现 | Eureka、Consul、Nacos | 服务注册、发现、健康检查 |
| 服务调用 | OpenFeign、Ribbon | 声明式HTTP客户端、负载均衡 |
| API网关 | Spring Cloud Gateway | 路由、过滤、限流、认证 |
| 配置管理 | Spring Cloud Config、Nacos | 集中化配置管理 |
| 断路器 | Resilience4j、Sentinel | 容错、熔断、降级 |
| 分布式追踪 | Sleuth + Zipkin、SkyWalking | 链路追踪、性能分析 |
| 消息驱动 | Spring Cloud Stream | 消息队列集成 |
Spring Cloud 采用伦敦地铁站名称作为版本代号(如Hoxton、Ilford),现在已改为日历化版本(如2020.0.x)。
版本对应关系:
| Spring Boot | Spring Cloud |
|---|---|
| 3.5.x | 2025.0.x (Northfields) |
| 3.4.x | 2024.0.x (Moorgate) |
| 3.2.x / 3.3.x | 2023.0.x (Leyton) |
| 2.7.x | 2021.0.x (Jubilee) |
| 2.6.x | 2021.0.x (Jubilee) |
| 2.5.x | 2020.0.x (Ilford) |
| 2.4.x | 2020.0.x (Ilford) |
Spring Boot是构建微服务的理想框架,因为它提供了:
推荐的项目结构:
microservice-project/
├── eureka-server/ # 服务注册中心
│ ├── src/main/java/
│ └── pom.xml
├── gateway-service/ # API网关
│ ├── src/main/java/
│ └── pom.xml
├── user-service/ # 用户服务
│ ├── src/main/java/
│ │ └── com/example/user/
│ │ ├── controller/
│ │ ├── service/
│ │ ├── repository/
│ │ └── entity/
│ └── pom.xml
├── order-service/ # 订单服务
│ ├── src/main/java/
│ └── pom.xml
└── pom.xml # 父POM,管理公共依赖服务注册: 服务启动时向注册中心注册自己的地址和端口
服务发现: 服务消费者从注册中心获取服务提供者的地址列表
心跳机制: 服务定期向注册中心发送心跳,证明自己存活
健康检查: 注册中心定期检查服务健康状态,剔除不健康服务
Eureka 是 Netflix 开源的服务注册与发现组件,是 Spring Cloud 的默认选择之一。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>启动类:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}配置文件:
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
# 自己是注册中心,不需要注册自己
registerWithEureka: false
# 不需要拉取服务列表
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
server:
# 关闭自我保护模式(开发环境)
enable-self-preservation: false
# 清理间隔(默认60秒)
eviction-interval-timer-in-ms: 5000
spring:
application:
name: eureka-serverEureka 自我保护机制:
Eureka 在运行期间会统计心跳失败比例,如果15分钟内低于85%,Eureka会进入自我保护模式:
生产环境建议:
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>启动类:
@SpringBootApplication
@EnableEurekaClient // 或使用 @EnableDiscoveryClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}配置文件:
spring:
application:
name: user-service # 服务名称,用于服务发现
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
# 拉取服务列表间隔(默认30秒)
registry-fetch-interval-seconds: 30
instance:
# 使用IP地址注册
prefer-ip-address: true
# 实例ID格式
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
# 心跳间隔(默认30秒)
lease-renewal-interval-in-seconds: 30
# 服务过期时间(默认90秒)
lease-expiration-duration-in-seconds: 90
server:
port: 8081多节点Eureka集群:
# Eureka节点1配置
server:
port: 8761
eureka:
instance:
hostname: eureka1
client:
serviceUrl:
defaultZone: http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
---
# Eureka节点2配置
server:
port: 8762
eureka:
instance:
hostname: eureka2
client:
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka3:8763/eureka/
---
# Eureka节点3配置
server:
port: 8763
eureka:
instance:
hostname: eureka3
client:
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/客户端连接集群:
eureka:
client:
serviceUrl:
defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/Consul 是 HashiCorp 公司开源的服务发现和配置管理工具。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>配置文件:
spring:
application:
name: user-service
cloud:
consul:
host: localhost
port: 8500
discovery:
# 服务名称
service-name: ${spring.application.name}
# 健康检查路径
health-check-path: /actuator/health
# 健康检查间隔
health-check-interval: 15s
# 实例ID
instance-id: ${spring.application.name}:${spring.cloud.client.ip-address}:${server.port}
# 使用IP地址注册
prefer-ip-address: true
# 标签
tags: version=1.0,author=team-user
server:
port: 8081Nacos 是阿里巴巴开源的动态服务发现、配置管理和服务管理平台。
添加依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>配置文件:
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 命名空间
namespace: dev
# 分组
group: DEFAULT_GROUP
# 集群名称
cluster-name: DEFAULT
server:
port: 8081| 特性 | Eureka | Consul | Nacos |
|---|---|---|---|
| CAP理论 | AP(可用性+分区容错) | CP(一致性+分区容错) | AP/CP可切换 |
| 健康检查 | 心跳检测 | TCP/HTTP/Script | TCP/HTTP/MySQL |
| 配置管理 | 需配合Spring Cloud Config | 内置KV存储 | 内置配置管理 |
| 多数据中心 | 支持 | 支持 | 支持 |
| 管理界面 | 有 | 有 | 有 |
| 社区活跃度 | 维护模式 | 活跃 | 活跃 |
选择建议:
| 特性 | 同步通信 | 异步通信 |
|---|---|---|
| 响应时间 | 实时响应 | 延迟处理 |
| 耦合度 | 强耦合 | 松耦合 |
| 可靠性 | 需要重试机制 | 消息队列保证 |
| 适用场景 | 实时查询、事务操作 | 异步任务、事件通知 |
| 技术选型 | RestTemplate、Feign | RabbitMQ、Kafka |
RestTemplate 是 Spring 提供的同步HTTP客户端,结合@LoadBalanced注解可以实现客户端负载均衡。
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
// 设置超时时间
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000); // 连接超时3秒
factory.setReadTimeout(5000); // 读取超时5秒
return new RestTemplate(factory);
}
}@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
// GET请求
public User getUserById(Long id) {
// 使用服务名替代IP地址
return restTemplate.getForObject(
"http://user-service/users/" + id,
User.class
);
}
// GET请求(带参数)
public List<User> getUsers(List<Long> ids) {
String url = "http://user-service/users?ids={ids}";
Map<String, String> params = new HashMap<>();
params.put("ids", StringUtils.join(ids, ","));
return restTemplate.getForObject(url, List.class, params);
}
// POST请求
public User createUser(User user) {
return restTemplate.postForObject(
"http://user-service/users",
user,
User.class
);
}
// PUT请求
public void updateUser(Long id, User user) {
restTemplate.put("http://user-service/users/" + id, user);
}
// DELETE请求
public void deleteUser(Long id) {
restTemplate.delete("http://user-service/users/" + id);
}
// 使用ResponseEntity获取详细信息
public ResponseEntity<User> getUserWithHeaders(Long id) {
return restTemplate.getForEntity(
"http://user-service/users/" + id,
User.class
);
}
}WebClient 是 Spring WebFlux 提供的非阻塞HTTP客户端,支持响应式编程。
@Configuration
public class WebClientConfig {
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder()
.baseUrl("http://user-service")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
}
}@Service
public class OrderService {
@Autowired
private WebClient.Builder webClientBuilder;
// 同步获取
public User getUserById(Long id) {
return webClientBuilder.build()
.get()
.uri("/users/{id}", id)
.retrieve()
.bodyToMono(User.class)
.block(); // 阻塞获取结果
}
// 异步响应式
public Mono<User> getUserByIdAsync(Long id) {
return webClientBuilder.build()
.get()
.uri("/users/{id}", id)
.retrieve()
.bodyToMono(User.class);
}
// 处理错误
public Mono<User> getUserWithErrorHandling(Long id) {
return webClientBuilder.build()
.get()
.uri("/users/{id}", id)
.retrieve()
.onStatus(
status -> status.is4xxClientError(),
response -> Mono.just(new UserNotFoundException("User not found"))
)
.bodyToMono(User.class)
.onErrorResume(e -> Mono.just(new User(-1L, "Default User")));
}
// 流式处理
public Flux<User> getAllUsers() {
return webClientBuilder.build()
.get()
.uri("/users")
.retrieve()
.bodyToFlux(User.class);
}
}OpenFeign 是声明式HTTP客户端,通过接口和注解定义HTTP请求,使代码更简洁优雅。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>@SpringBootApplication
@EnableFeignClients // 启用Feign客户端
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}// 基本用法
@FeignClient(name = "user-service") // 指定服务名
public interface UserServiceClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
@GetMapping("/users")
List<User> getUsers(@RequestParam("ids") List<Long> ids);
@PostMapping("/users")
User createUser(@RequestBody User user);
@PutMapping("/users/{id}")
User updateUser(@PathVariable("id") Long id, @RequestBody User user);
@DeleteMapping("/users/{id}")
void deleteUser(@PathVariable("id") Long id);
}
// 指定URL(用于测试或调用外部服务)
@FeignClient(name = "external-api", url = "https://api.example.com")
public interface ExternalApiClient {
@GetMapping("/data")
String getData();
}
// 使用配置类
@FeignClient(
name = "user-service",
configuration = FeignConfig.class,
fallback = UserServiceFallback.class
)
public interface UserServiceClient {
// ...
}@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel() {
return Logger.Level.FULL; // 日志级别
}
@Bean
public Request.Options requestOptions() {
return new Request.Options(
5000, // 连接超时5秒
10000 // 读取超时10秒
);
}
@Bean
public Retryer retryer() {
return new Retryer.Default(
100, // 初始间隔100ms
1000, // 最大间隔1秒
3 // 最大重试次数
);
}
}application.yml 配置:
feign:
client:
config:
default: # 全局配置
connectTimeout: 5000
readTimeout: 10000
loggerLevel: FULL
user-service: # 特定服务配置
connectTimeout: 3000
readTimeout: 5000@Service
public class OrderService {
@Autowired
private UserServiceClient userServiceClient;
public Order createOrder(Long userId, List<Long> productIds) {
// 调用用户服务
User user = userServiceClient.getUserById(userId);
// 创建订单
Order order = new Order();
order.setUserId(userId);
order.setUsername(user.getUsername());
// ...
return order;
}
}// 降级实现类
@Component
public class UserServiceFallback implements UserServiceClient {
@Override
public User getUserById(Long id) {
// 返回默认用户或从缓存获取
return new User(id, "Default User", "default@example.com");
}
@Override
public List<User> getUsers(List<Long> ids) {
return Collections.emptyList();
}
// ... 其他方法实现
}
// Feign接口指定fallback
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {
// ...
}启用Hystrix降级(旧版Spring Cloud):
feign:
hystrix:
enabled: true<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
# 消息确认机制
publisher-confirm-type: correlated
publisher-returns: true
template:
mandatory: true
listener:
simple:
acknowledge-mode: manual # 手动确认
concurrency: 3
max-concurrency: 10@Service
public class OrderService {
@Autowired
private RabbitTemplate rabbitTemplate;
// 发送订单创建消息
public void sendOrderCreatedEvent(Order order) {
rabbitTemplate.convertAndSend(
"order.exchange", // 交换机
"order.created", // 路由键
order, // 消息内容
message -> {
message.getMessageProperties().setMessageId(UUID.randomUUID().toString());
return message;
}
);
}
// 发送延时消息
public void sendDelayMessage(Order order, long delayMillis) {
rabbitTemplate.convertAndSend(
"delay.exchange",
"delay.order",
order,
message -> {
message.getMessageProperties().setExpiration(String.valueOf(delayMillis));
return message;
}
);
}
}@Component
public class NotificationConsumer {
@RabbitListener(queues = "notification.queue")
public void handleOrderCreated(Order order, Channel channel,
@Header(AmqpHeaders.DELIVERY_TAG) long tag) {
try {
// 处理订单创建通知
System.out.println("Received order: " + order.getId());
// 发送邮件或短信通知
sendNotification(order);
// 手动确认消息
channel.basicAck(tag, false);
} catch (Exception e) {
// 处理失败,消息重新入队
try {
channel.basicNack(tag, false, true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
private void sendNotification(Order order) {
// 发送通知逻辑
}
}API 网关是微服务架构中的重要组件,作为系统的统一入口,提供以下功能:
Spring Cloud Gateway 是 Spring Cloud 官方推荐的API网关,基于 Spring WebFlux 与 Project Reactor 构建的响应式网关。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>spring:
application:
name: gateway-service
cloud:
gateway:
# 路由配置
routes:
# 用户服务路由
- id: user-service
uri: lb://user-service # lb表示从注册中心获取服务
predicates:
- Path=/api/users/** # 路径匹配
filters:
- StripPrefix=1 # 去掉路径前缀/api
# 订单服务路由
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- StripPrefix=1
# 商品服务路由(带时间限制)
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
- After=2024-01-01T00:00:00+08:00 # 在指定时间后生效
filters:
- StripPrefix=1
# 管理后台路由(带请求头限制)
- id: admin-service
uri: lb://admin-service
predicates:
- Path=/api/admin/**
- Header=X-Request-Id, \d+ # 请求头必须包含X-Request-Id且值为数字
filters:
- StripPrefix=1
server:
port: 8080
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/Spring Cloud Gateway 提供了多种路由断言:
spring:
cloud:
gateway:
routes:
- id: example-service
uri: lb://example-service
predicates:
# 路径匹配
- Path=/api/**
# 请求方法匹配
- Method=GET,POST
# 请求头匹配
- Header=X-Request-Id, \d+
# 请求参数匹配
- Query=token
# Cookie匹配
- Cookie=session, abc
# 时间匹配
- After=2024-01-01T00:00:00+08:00
- Before=2024-12-31T23:59:59+08:00
- Between=2024-01-01T00:00:00+08:00, 2024-12-31T23:59:59+08:00
# 远程地址匹配
- RemoteAddr=192.168.1.1/24
# 权重路由(灰度发布,同组内多条路由按权重分摊流量,如另一条配 group1, 2 即 80%/20%)
- Weight=group1, 8内置过滤器:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
# 添加请求头
- AddRequestHeader=X-Request-Foo, Bar
# 添加请求参数
- AddRequestParameter=foo, bar
# 添加响应头
- AddResponseHeader=X-Response-Foo, Bar
# 去掉路径前缀
- StripPrefix=1
# 添加路径前缀
- PrefixPath=/api
# 重定向
- RedirectTo=302, https://example.com
# 重试
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
methods: GET
backoff:
firstBackoff: 100ms
maxBackoff: 500ms
factor: 2
# 限流(基于令牌桶算法)
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 每秒生成令牌数
redis-rate-limiter.burstCapacity: 20 # 令牌桶容量
key-resolver: "#{@userKeyResolver}" # 限流key解析器@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {
private static final String AUTHORIZE_TOKEN = "Authorization";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
// 白名单路径直接放行
if (isWhitePath(path)) {
return chain.filter(exchange);
}
// 检查Authorization头
String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN);
if (token == null || token.isEmpty()) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
String body = "{\"code\":401,\"message\":\"未授权访问\"}";
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
return response.writeWith(Mono.just(buffer));
}
// 验证Token(这里简化处理,实际应调用认证服务)
try {
// String userId = JwtUtil.parseToken(token);
// 将用户信息添加到请求头
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-Id", "userId")
.build();
return chain.filter(exchange.mutate().request(mutatedRequest).build());
} catch (Exception e) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
}
private boolean isWhitePath(String path) {
return path.startsWith("/api/auth/login")
|| path.startsWith("/api/auth/register")
|| path.startsWith("/api/public/");
}
@Override
public int getOrder() {
return -100; // 优先级高,先执行
}
}@Component
@Slf4j
public class AccessLogFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
long startTime = System.currentTimeMillis();
// 记录请求日志
log.info("Request: {} {} from {}",
request.getMethod(),
request.getURI(),
request.getRemoteAddress());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 记录响应日志
long duration = System.currentTimeMillis() - startTime;
ServerHttpResponse response = exchange.getResponse();
log.info("Response: {} - {} ({}ms)",
response.getStatusCode(),
request.getURI(),
duration);
}));
}
@Override
public int getOrder() {
return -200; // 日志过滤器最先执行
}
}@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedMethod("*");
config.addAllowedHeader("*");
config.setAllowCredentials(true);
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}Spring Cloud Config 提供集中化的配置管理,支持Git、SVN、本地文件系统等存储方式。
添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>启动类:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}配置文件:
server:
port: 8888
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/your-repo/config-repo
username: your-username
password: your-password
search-paths: '{application}' # 根据应用名搜索目录
default-label: main # 默认分支
# 本地文件系统(测试用)
# native:
# search-locations: classpath:/config
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka//{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties示例:
config-repo/
├── user-service.yml # 默认配置
├── user-service-dev.yml # 开发环境配置
├── user-service-prod.yml # 生产环境配置
└── application.yml # 公共配置添加依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>bootstrap.yml(优先级高于application.yml):
spring:
application:
name: user-service
cloud:
config:
uri: http://localhost:8888 # 配置服务器地址
fail-fast: true # 连接失败快速失败
retry:
initial-interval: 1000
max-attempts: 6
max-interval: 2000
multiplier: 1.1
label: main # 分支
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/使用@RefreshScope:
@RestController
@RefreshScope // 支持配置热更新
public class ConfigController {
@Value("${app.message:Default Message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}触发配置更新:
# POST请求到客户端的/actuator/refresh端点
curl -X POST http://localhost:8081/actuator/refresh开启actuator端点:
management:
endpoints:
web:
exposure:
include: refresh,health,infoNacos 提供更简洁的配置管理方式,支持配置热更新和灰度发布。
配置文件:
spring:
application:
name: user-service
cloud:
nacos:
# 服务发现配置
discovery:
server-addr: localhost:8848
# 配置中心配置
config:
server-addr: localhost:8848
namespace: dev
group: DEFAULT_GROUP
file-extension: yaml
# 扩展配置
extension-configs:
- data-id: common.yaml
group: DEFAULT_GROUP
refresh: true在微服务架构中,服务之间的调用是分布式的,当某个服务出现故障时,如果不进行隔离,会导致:
断路器模式通过以下机制解决这些问题:
Resilience4j 是轻量级的容错库,提供了断路器、限流器、重试等功能。
<!-- Boot 2.x 用 resilience4j-spring-boot2,Boot 3.x 应改用 resilience4j-spring-boot3 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>resilience4j:
circuitbreaker:
configs:
default:
# 断路器状态转换配置
failureRateThreshold: 50 # 失败率阈值50%
slowCallRateThreshold: 100 # 慢调用率阈值
slowCallDurationThreshold: 2s # 慢调用时间阈值
permittedNumberOfCallsInHalfOpenState: 3 # 半开状态允许的调用数
slidingWindowType: COUNT_BASED # 滑动窗口类型(基于调用次数)
slidingWindowSize: 10 # 滑动窗口大小
minimumNumberOfCalls: 5 # 最小调用次数
waitDurationInOpenState: 10s # 断路器打开状态等待时间
automaticTransitionFromOpenToHalfOpenEnabled: true # 自动转换到半开状态
instances:
userService:
baseConfig: default
failureRateThreshold: 60
waitDurationInOpenState: 20s
orderService:
baseConfig: default
failureRateThreshold: 40
waitDurationInOpenState: 30s
# 限流配置
ratelimiter:
configs:
default:
limitForPeriod: 10 # 每个周期限制请求数
limitRefreshPeriod: 1s # 周期
timeoutDuration: 0 # 等待获取许可的超时时间
instances:
userService:
baseConfig: default
# 重试配置
retry:
configs:
default:
maxAttempts: 3 # 最大重试次数
waitDuration: 500ms # 重试等待时间
enableExponentialBackoff: true # 指数退避
exponentialBackoffMultiplier: 2
instances:
userService:
baseConfig: default@Service
public class OrderService {
@Autowired
private UserServiceClient userServiceClient;
// 使用断路器
@CircuitBreaker(name = "userService", fallbackMethod = "fallbackGetUser")
public User getUserById(Long id) {
return userServiceClient.getUserById(id);
}
// 降级方法(参数必须与原方法一致,最后可以加Exception参数)
public User fallbackGetUser(Long id, Exception ex) {
log.warn("Fallback for getUserById: {}", ex.getMessage());
// 返回默认用户或从缓存获取
return new User(id, "Default User", "default@example.com");
}
// 组合使用断路器、限流、重试
@CircuitBreaker(name = "userService", fallbackMethod = "fallbackGetUser")
@RateLimiter(name = "userService")
@Retry(name = "userService")
public User getUserWithResilience(Long id) {
return userServiceClient.getUserById(id);
}
// 使用超时控制
@Timeout(value = 3, unit = ChronoUnit.SECONDS)
public User getUserWithTimeout(Long id) {
return userServiceClient.getUserById(id);
}
}management:
endpoints:
web:
exposure:
include: health,circuitbreakers
endpoint:
health:
show-details: always
health:
circuitbreakers:
enabled: true访问监控端点:
curl http://localhost:8081/actuator/health响应示例:
{
"status": "UP",
"components": {
"circuitBreakers": {
"status": "UP",
"details": {
"circuitBreakers": [
{
"name": "userService",
"status": "CLOSED",
"details": {
"failureRate": "0.0%",
"slowCallRate": "0.0%",
"numberOfBufferedCalls": 5,
"numberOfFailedCalls": 0
}
}
]
}
}
}
}CLOSED (关闭状态)
↓ 失败率超过阈值
OPEN (打开状态) → 快速失败,不执行实际调用
↓ 等待时间结束
HALF_OPEN (半开状态) → 允许少量请求通过
↓ 成功率恢复正常 ↓ 失败率仍高
CLOSED OPEN在微服务架构中,一个请求可能经过多个服务,调用链路复杂。当出现性能问题或故障时,需要快速定位问题所在。
分布式追踪系统提供:
版本注: Spring Cloud Sleuth 仅适用于 Spring Boot 2.x / Spring Cloud 2021.x 及更早版本,自 Spring Cloud 2022.0(Kilburn, 配套 Boot 3.x)起已被 Micrometer Tracing 取代(配合 Zipkin bridge 依赖
micrometer-tracing-bridge-brave与zipkin-reporter-brave)。以下内容适用于 Boot 2.x 项目;Boot 3.x 项目的配置属性迁移为management.tracing.sampling.probability与management.zipkin.tracing.endpoint。
<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>spring:
application:
name: user-service
sleuth:
sampler:
probability: 1.0 # 采样率100%(生产环境应降低到0.1-0.5)
zipkin:
base-url: http://localhost:9411 # Zipkin服务器地址
sender:
type: web # 使用HTTP发送追踪数据
# 日志配置(查看TraceId和SpanId)
logging:
level:
org.springframework.web.servlet.DispatcherServlet: DEBUG
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-},%X{spanId:-}] %-5level %logger{36} - %msg%n"2024-01-01 12:00:00.123 [http-nio-8081-exec-1] [a1b2c3d4e5f6g7h8,1234567890abcdef] INFO c.e.user.controller.UserController - Getting user by id: 1a1b2c3d4e5f6g7h8 - TraceId(整个调用链唯一)1234567890abcdef - SpanId(单个服务调用唯一)@Service
public class UserService {
@Autowired
private Tracer tracer;
public User getUserById(Long id) {
// 创建新的Span
Span span = tracer.nextSpan().name("getUserById");
try (Tracer.SpanInScope ws = tracer.withSpan(span.start())) {
// 业务逻辑
User user = userRepository.findById(id);
// 添加标签
span.tag("user.id", String.valueOf(id));
span.tag("user.name", user.getUsername());
return user;
} finally {
span.end();
}
}
}启动Zipkin服务器:
java -jar zipkin-server-2.24.0-exec.jar访问 http://localhost:9411 可以查看:
SkyWalking 是APM(应用性能监控)系统,提供了更强大的监控能力。
特点:
启动方式:
java -javaagent:/path/to/skywalking-agent.jar \
-Dskywalking.agent.service_name=user-service \
-Dskywalking.collector.backend_service=localhost:11800 \
-jar user-service.jarSpring Cloud Stream 提供了统一的消息驱动编程模型,支持多种消息中间件(RabbitMQ、Kafka、RocketMQ等)。
<!-- RabbitMQ -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<!-- Kafka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-kafka</artifactId>
</dependency>spring:
cloud:
stream:
# 绑定配置
bindings:
# 输出通道
orderOutput:
destination: order-topic # 目的地(队列/主题)
content-type: application/json
# 输入通道
orderInput:
destination: order-topic
group: order-group # 消费者组(同一个组只有一个消费者消费消息)
content-type: application/json
# RabbitMQ特定配置
rabbit:
bindings:
orderInput:
consumer:
# 死信队列配置
auto-bind-dlq: true
republish-to-dlq: true
# Kafka特定配置
kafka:
bindings:
orderInput:
consumer:
auto-commit-offset: false
binder:
brokers: localhost:9092版本注:
@EnableBinding与@StreamListener自 Spring Cloud Stream 3.1 起废弃、4.0 起移除。新项目应使用函数式编程模型(定义Supplier/Function/ConsumerBean 并通过spring.cloud.function.definition绑定通道)。
// 自定义消息通道接口
public interface OrderChannel {
String OUTPUT = "orderOutput";
String INPUT = "orderInput";
@Output(OUTPUT)
MessageChannel output();
@Input(INPUT)
SubscribableChannel input();
}
// 或使用内置的Source和Sink@EnableBinding(OrderChannel.class)
@Service
public class OrderService {
@Autowired
private OrderChannel orderChannel;
public void sendOrderCreatedEvent(Order order) {
Message<Order> message = MessageBuilder
.withPayload(order)
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
.setHeader("orderId", order.getId())
.build();
orderChannel.output().send(message);
}
// 延迟消息
public void sendDelayedOrder(Order order, long delaySeconds) {
Message<Order> message = MessageBuilder
.withPayload(order)
.setHeader("x-delay", delaySeconds * 1000) // RabbitMQ延迟插件
.build();
orderChannel.output().send(message);
}
}@EnableBinding(OrderChannel.class)
@Service
public class NotificationService {
@StreamListener(OrderChannel.INPUT)
public void handleOrderCreated(Order order) {
// 处理订单创建事件
System.out.println("Received order: " + order.getId());
// 发送邮件或短信通知
sendNotification(order);
}
// 条件消费(根据消息头过滤)
@StreamListener(
target = OrderChannel.INPUT,
condition = "headers['orderType'] == 'VIP'"
)
public void handleVipOrder(Order order) {
// 处理VIP订单
System.out.println("VIP Order: " + order.getId());
}
// 错误处理
@ServiceActivator(inputChannel = "order-topic.errors")
public void handleError(ErrorMessage errorMessage) {
System.err.println("Message processing failed: " + errorMessage);
}
private void sendNotification(Order order) {
// 发送通知逻辑
}
}消息分组:
spring:
cloud:
stream:
bindings:
orderInput:
destination: order-topic
group: order-group # 同一个组内只有一个消费者消费消息消息分区:
spring:
cloud:
stream:
bindings:
orderOutput:
destination: order-topic
producer:
partition-key-expression: payload.id # 分区key
partition-count: 3 # 分区数
orderInput:
destination: order-topic
group: order-group
consumer:
partitioned: true
instance-count: 3 # 消费者实例数
instance-index: 0 # 当前实例索引# 多阶段构建
FROM maven:3.8.6-openjdk-17 AS build
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
# 运行阶段
FROM openjdk:17-jdk-slim
WORKDIR /app
# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 复制jar文件
COPY --from=build /app/target/user-service.jar app.jar
# 修改文件所有者
RUN chown -R appuser:appuser /app
# 切换到非root用户
USER appuser
# 暴露端口
EXPOSE 8080
# JVM参数
ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]version: '3.8'
services:
# Eureka服务注册中心
eureka-server:
build: ./eureka-server
container_name: eureka-server
ports:
- "8761:8761"
environment:
- SPRING_PROFILES_ACTIVE=docker
networks:
- microservice-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8761/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
# API网关
gateway-service:
build: ./gateway-service
container_name: gateway-service
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
depends_on:
eureka-server:
condition: service_healthy
networks:
- microservice-network
# 用户服务
user-service:
build: ./user-service
container_name: user-service
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/user_db
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=root123
depends_on:
eureka-server:
condition: service_healthy
mysql:
condition: service_healthy
networks:
- microservice-network
deploy:
replicas: 2 # 运行2个实例
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
# 订单服务
order-service:
build: ./order-service
container_name: order-service
ports:
- "8082:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
depends_on:
eureka-server:
condition: service_healthy
user-service:
condition: service_started
networks:
- microservice-network
# MySQL数据库
mysql:
image: mysql:8.0
container_name: mysql
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=user_db
volumes:
- mysql-data:/var/lib/mysql
- ./init-scripts:/docker-entrypoint-initdb.d
networks:
- microservice-network
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
# Redis缓存
redis:
image: redis:7-alpine
container_name: redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
networks:
- microservice-network
# RabbitMQ消息队列
rabbitmq:
image: rabbitmq:3-management-alpine
container_name: rabbitmq
ports:
- "5672:5672"
- "15672:15672" # 管理界面
environment:
- RABBITMQ_DEFAULT_USER=admin
- RABBITMQ_DEFAULT_PASS=admin123
volumes:
- rabbitmq-data:/var/lib/rabbitmq
networks:
- microservice-network
# Zipkin链路追踪
zipkin:
image: openzipkin/zipkin:latest
container_name: zipkin
ports:
- "9411:9411"
networks:
- microservice-network
networks:
microservice-network:
driver: bridge
volumes:
mysql-data:
redis-data:
rabbitmq-data:apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
labels:
app: user-service
spec:
replicas: 3 # 运行3个副本
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: your-registry/user-service:1.0.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "k8s"
- name: EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE
value: "http://eureka-server:8761/eureka"
- name: SPRING_DATASOURCE_URL
valueFrom:
configMapKeyRef:
name: user-service-config
key: database.url
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: user-service-secret
key: database.password
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 8080
targetPort: 8080
type: ClusterIPapiVersion: v1
kind: ConfigMap
metadata:
name: user-service-config
data:
database.url: "jdbc:mysql://mysql-service:3306/user_db"
redis.host: "redis-service"apiVersion: v1
kind: Secret
metadata:
name: user-service-secret
type: Opaque
data:
database.password: cm9vdDEyMw== # base64编码 ┌─────────────┐
│ 用户端 │
└──────┬──────┘
│
┌──────▼──────┐
│ API 网关 │
│ (Gateway) │
└──────┬──────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ 用户服务 │ │ 商品服务 │ │ 订单服务 │
│ User Service │ │Product Service│ │Order Service │
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
│ │ │
┌───────▼───────┐ ┌───────▼───────┐ ┌───────▼───────┐
│ 用户数据库 │ │ 商品数据库 │ │ 订单数据库 │
│ (MySQL) │ │ (MySQL) │ │ (MongoDB) │
└───────────────┘ └───────────────┘ └───────────────┘
┌──────────────────────────────────────┐
│ 基础设施服务 │
├──────────────────────────────────────┤
│ Eureka Server - 服务注册中心 │
│ Config Server - 配置中心 │
│ Zipkin Server - 链路追踪 │
│ RabbitMQ - 消息队列 │
│ Redis - 分布式缓存 │
└──────────────────────────────────────┘1. 用户服务(User Service)
2. 商品服务(Product Service)
3. 订单服务(Order Service)
4. 支付服务(Payment Service)
5. 物流服务(Shipping Service)
6. 通知服务(Notification Service)
下单流程:
1. 用户发起下单请求
↓
2. API网关鉴权和路由
↓
3. 订单服务创建订单(状态: 待支付)
↓
4. 调用商品服务扣减库存
↓
5. 调用用户服务获取用户信息
↓
6. 发送订单创建消息到RabbitMQ
↓
7. 支付服务监听消息,创建支付单
↓
8. 用户完成支付
↓
9. 支付服务更新支付状态,发送支付成功消息
↓
10. 订单服务监听消息,更新订单状态为已支付
↓
11. 物流服务监听消息,创建物流单
↓
12. 通知服务发送订单成功通知分布式事务解决方案:
最终一致性(推荐):
Saga模式:
TCC模式(Try-Confirm-Cancel):
订单库存扣减示例(Saga模式):
@Service
public class OrderSagaService {
@Autowired
private OrderService orderService;
@Autowired
private ProductService productClient;
@Autowired
private PaymentService paymentClient;
// 创建订单Saga流程
public void createOrderSaga(Order order) {
try {
// 1. 创建订单
Order createdOrder = orderService.createOrder(order);
// 2. 扣减库存
productClient.deductStock(order.getProductId(), order.getQuantity());
// 3. 创建支付单
paymentClient.createPayment(createdOrder.getId(), order.getTotalAmount());
} catch (Exception e) {
// 补偿操作
compensateOrder(order);
throw e;
}
}
// 补偿操作
private void compensateOrder(Order order) {
// 恢复库存
try {
productClient.restoreStock(order.getProductId(), order.getQuantity());
} catch (Exception e) {
// 记录日志,人工处理
log.error("Failed to restore stock: {}", e.getMessage());
}
// 取消订单
try {
orderService.cancelOrder(order.getId());
} catch (Exception e) {
log.error("Failed to cancel order: {}", e.getMessage());
}
}
}问题: 当某个服务出现故障时,故障向调用链上游传播,导致整个系统崩溃。
解决方案:
示例配置:
resilience4j:
circuitbreaker:
instances:
userService:
failureRateThreshold: 50 # 失败率50%触发熔断
waitDurationInOpenState: 20s # 熔断持续20秒
slidingWindowSize: 10问题: 微服务架构下,每个服务有独立的数据库,跨服务事务难以保证一致性。
解决方案:
本地消息表示例:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private MessageRepository messageRepository;
@Transactional
public void createOrder(Order order) {
// 1. 保存订单
orderRepository.save(order);
// 2. 保存消息到本地消息表(同一事务)
Message message = new Message();
message.setTopic("order.created");
message.setContent(JSON.toJSONString(order));
message.setStatus("PENDING");
messageRepository.save(message);
}
// 定时任务扫描并发送消息
@Scheduled(fixedDelay = 5000)
public void sendPendingMessages() {
List<Message> messages = messageRepository.findByStatus("PENDING");
for (Message message : messages) {
try {
rabbitTemplate.convertAndSend(
message.getTopic(),
message.getContent()
);
message.setStatus("SENT");
messageRepository.save(message);
} catch (Exception e) {
log.error("Failed to send message: {}", message.getId());
}
}
}
}问题: 网络延迟、服务响应慢导致调用超时。
解决方案:
示例配置:
feign:
client:
config:
default:
connectTimeout: 5000 # 连接超时5秒
readTimeout: 10000 # 读取超时10秒
resilience4j:
retry:
instances:
userService:
maxAttempts: 3 # 重试3次
waitDuration: 500ms
enableExponentialBackoff: true问题: 新服务上线后,其他服务无法及时发现;服务下线后,调用仍然失败。
解决方案:
示例配置:
eureka:
client:
registry-fetch-interval-seconds: 10 # 每10秒拉取服务列表
instance:
lease-renewal-interval-in-seconds: 10 # 每10秒发送心跳
lease-expiration-duration-in-seconds: 30 # 30秒未心跳视为失效
server:
eviction-interval-timer-in-ms: 5000 # 每5秒清理失效服务问题: 多个服务、多个环境的配置难以统一管理和更新。
解决方案:
Nacos配置管理示例:
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
namespace: prod # 环境隔离
group: ORDER_GROUP # 业务分组
file-extension: yaml
shared-configs: # 共享配置
- data-id: common.yaml
refresh: true问题: 日志分散在各个服务中,排查问题困难。
解决方案:
日志格式示例:
<!-- logback-spring.xml -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{traceId:-},%X{spanId:-}] %-5level %logger{36} - %msg%n</pattern>问题: 缺乏系统性能监控,无法及时发现性能瓶颈。
解决方案:
Prometheus配置示例:
# prometheus.yml
scrape_configs:
- job_name: 'spring-boot-apps'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['user-service:8080', 'order-service:8080']Spring Boot开启Prometheus端点:
management:
endpoints:
web:
exposure:
include: prometheus,health,info
metrics:
tags:
application: ${spring.application.name}问题: 每个服务都需要独立的认证,难以统一管理。
解决方案:
JWT认证流程:
1. 用户登录 → 认证服务验证
2. 认证服务颁发JWT令牌
3. 客户端携带JWT访问API网关
4. API网关验证JWT,提取用户信息
5. 将用户信息传递给后端服务
6. 后端服务根据用户信息进行授权网关JWT验证示例:
@Component
public class JwtAuthenticationFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders().getFirst("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
try {
// 验证JWT
Claims claims = Jwts.parser()
.setSigningKey("secret-key")
.parseClaimsJws(token)
.getBody();
// 将用户信息添加到请求头
ServerHttpRequest request = exchange.getRequest().mutate()
.header("X-User-Id", claims.getSubject())
.header("X-User-Name", claims.get("username", String.class))
.build();
return chain.filter(exchange.mutate().request(request).build());
} catch (Exception e) {
// JWT无效
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}1. 什么是微服务架构?它与单体架构有什么区别?
微服务架构是将应用程序构建为一组小型、自治服务的方法,每个服务运行在自己的进程中,通过轻量级机制通信。
与单体架构的区别:
2. 微服务架构的优缺点是什么?
优点:
缺点:
3. 如何进行微服务拆分?
拆分原则:
示例:
4. 什么是服务注册与发现?有哪些常用组件?
概念:
常用组件:
5. 如何实现服务的负载均衡?
客户端负载均衡:
服务端负载均衡:
负载均衡策略:
6. 如何保证微服务的数据一致性?
解决方案:
最终一致性(推荐):
Saga模式:
TCC模式:
本地消息表:
7. 什么是断路器模式?如何实现服务熔断和降级?
断路器模式:
实现方式:
示例:
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public User getUserById(Long id) {
return userServiceClient.getUserById(id);
}
public User fallback(Long id, Exception ex) {
return new User(id, "Default User");
}8. API网关的作用是什么?Spring Cloud Gateway如何使用?
API网关作用:
Spring Cloud Gateway使用:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=19. 如何实现分布式追踪?
解决方案:
核心概念:
实现方式:
10. 如何实现配置中心?配置如何热更新?
配置中心选择:
配置热更新:
@RestController
@RefreshScope
public class ConfigController {
@Value("${app.message}")
private String message;
}11. 如何设计一个电商系统的微服务架构?
服务拆分:
基础设施:
数据一致性:
12. 微服务架构下如何处理分布式事务?
场景: 下单流程涉及订单创建、库存扣减、支付等多个服务
解决方案:
// 订单服务
@Transactional
public void createOrder(Order order) {
orderRepository.save(order);
// 发送订单创建消息
rabbitTemplate.convertAndSend("order.created", order);
}
// 库存服务
@RabbitListener(queues = "stock.deduct")
public void deductStock(Order order) {
stockRepository.deduct(order.getProductId(), order.getQuantity());
}13. 如何实现微服务的灰度发布?
方案一: 网关层路由
spring:
cloud:
gateway:
routes:
- id: user-service-v1
uri: lb://user-service-v1
predicates:
- Path=/api/users/**
- Header=X-Version, v1
- id: user-service-v2
uri: lb://user-service-v2
predicates:
- Path=/api/users/**
- Header=X-Version, v2方案二: 权重路由
spring:
cloud:
gateway:
routes:
- id: user-service-v1
uri: lb://user-service-v1
predicates:
- Path=/api/users/**
- Weight=group1, 80 # 80%流量
- id: user-service-v2
uri: lb://user-service-v2
predicates:
- Path=/api/users/**
- Weight=group1, 20 # 20%流量方案三: Kubernetes滚动更新:
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 014. 如何保证微服务的高可用?
服务层:
数据层:
基础设施层:
监控告警:
15. Spring Cloud和Spring Cloud Alibaba的区别?
| 组件 | Spring Cloud | Spring Cloud Alibaba |
|---|---|---|
| 服务注册 | Eureka(维护模式) | Nacos |
| 配置中心 | Spring Cloud Config | Nacos |
| 断路器 | Resilience4j | Sentinel |
| 服务调用 | OpenFeign | Dubbo |
| 网关 | Spring Cloud Gateway | Spring Cloud Gateway |
选择建议:
Nacos优势:
Spring Boot与Spring Cloud生态系统为构建微服务架构提供了强大的支持。通过合理使用服务注册与发现、API网关、配置管理、断路器等组件,可以构建出健壮、可扩展的微服务系统。
微服务架构的关键成功因素:
何时选择微服务架构:
适合场景:
不适合场景:
演进路径:
单体架构 → 模块化单体 → 微服务架构
(初期) (业务增长) (业务复杂+团队成熟)微服务架构虽然带来了复杂性,但也提供了更高的灵活性和可维护性。在实践中需要权衡利弊,选择适合自己团队的架构方式。
| 特性 | 旧版(Spring Boot 2.x) | Spring Boot 3.5.x |
|---|---|---|
| 微服务组件 | Spring Cloud Netflix/2.x | Spring Cloud 2025.0.x(兼容 Boot 3.5) |
| 服务发现 | Eureka 等 | Nacos/Consul 更主流;Eureka 仍可用 |
| 网关 | Zuul(停更) | Spring Cloud Gateway(路由/限流) |
| 熔断 | Hystrix(停更) | Resilience4j / Sentinel |
| 配置中心 | Spring Cloud Config | 不变;Nacos 配置中心更流行 |
| 可观测性 | 各自为战 | Micrometer Tracing + OTel 统一 |