引言
随着业务规模的增长,单体应用在可维护性、可扩展性和团队协作方面的局限性日益凸显。微服务架构通过将大型应用拆分为一组松耦合、可独立部署的服务,有效解决了这些痛点。Spring
Cloud作为Java生态中最成熟的微服务框架,提供了一整套开箱即用的分布式系统解决方案。
本文将基于Spring Cloud
Alibaba技术栈,从服务注册与发现、负载均衡、熔断降级、API网关、配置中心到分布式链路追踪,系统性地讲解微服务架构的核心组件及其实战应用。
微服务架构全景
在深入各个组件之前,我们先通过架构图了解Spring
Cloud微服务系统的整体结构。
graph TB
Client[客户端] --> Gateway[Spring Cloud Gateway]
Gateway --> ServiceA[订单服务]
Gateway --> ServiceB[用户服务]
Gateway --> ServiceC[商品服务]
ServiceA --> Nacos[Nacos 注册/配置中心]
ServiceB --> Nacos
ServiceC --> Nacos
ServiceA --> Sentinel[Sentinel 熔断降级]
ServiceB --> Sentinel
ServiceC --> Sentinel
ServiceA -.-> ServiceB
ServiceA -.-> ServiceC
ServiceA --> Sleuth[Sleuth + Zipkin 链路追踪]
ServiceB --> Sleuth
ServiceC --> Sleuth
subgraph 基础设施层
Nacos
Sentinel
Sleuth
end
项目基础搭建
首先定义父工程的依赖管理,统一版本控制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <!-- pom.xml (父工程) --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2 .3 </version> </parent> <properties> <java.version>21 </java.version> <spring-cloud.version>2023.0 .0 </spring-cloud.version> <spring-cloud-alibaba.version>2023.0 .0 .0 </spring-cloud-alibaba.version> </properties> <dependencyManagement> <dependencies> <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
Nacos(Dynamic Naming and Configuration
Service)是阿里巴巴开源的服务注册与配置管理平台,它同时承担了注册中心和配置中心两个角色。
sequenceDiagram
participant Service as 微服务实例
participant Nacos as Nacos Server
participant Consumer as 服务消费者
Service->>Nacos: 1. 服务注册 (name, ip, port, metadata)
Service->>Nacos: 2. 定时心跳 (每5秒)
Consumer->>Nacos: 3. 查询服务列表
Nacos-->>Consumer: 4. 返回健康实例列表
Consumer->>Service: 5. 发起RPC调用
Note over Nacos: 15秒无心跳标记不健康
Note over Nacos: 30秒无心跳剔除实例
服务提供者配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 server: port: 8081 spring: application: name: user-service cloud: nacos: discovery: server-addr: localhost:8848 namespace: dev group: DEFAULT_GROUP ephemeral: true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @SpringBootApplication @EnableDiscoveryClient public class UserServiceApplication { public static void main (String[] args) { SpringApplication.run(UserServiceApplication.class, args); } }@RestController @RequestMapping("/api/users") public class UserController { @GetMapping("/{id}") public User getUserById (@PathVariable Long id) { return new User (id, "张三" , "[email protected] " ); } @GetMapping("/{id}/detail") public UserDetail getUserDetail (@PathVariable Long id) { return new UserDetail (id, "张三" , "[email protected] " , "北京市朝阳区" ); } }
服务消费者 - 使用OpenFeign
OpenFeign提供了声明式的HTTP客户端,通过接口注解的方式简化了服务间调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 @FeignClient(name = "user-service", fallbackFactory = UserClientFallbackFactory.class) public interface UserClient { @GetMapping("/api/users/{id}") User getUserById (@PathVariable("id") Long id) ; @GetMapping("/api/users/{id}/detail") UserDetail getUserDetail (@PathVariable("id") Long id) ; }@Component public class UserClientFallbackFactory implements FallbackFactory <UserClient> { @Override public UserClient create (Throwable cause) { return new UserClient () { @Override public User getUserById (Long id) { return new User (id, "未知用户" , "" ); } @Override public UserDetail getUserDetail (Long id) { return new UserDetail (id, "未知用户" , "" , "" ); } }; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Service @RequiredArgsConstructor public class OrderService { private final UserClient userClient; public OrderVO createOrder (OrderCreateDTO dto) { User user = userClient.getUserById(dto.getUserId()); Order order = new Order (); order.setOrderNo(generateOrderNo()); order.setUserId(user.getId()); order.setUserName(user.getName()); order.setAmount(dto.getAmount()); order.setStatus(OrderStatus.CREATED); orderRepository.save(order); return OrderVO.from(order); } }
负载均衡 - Spring Cloud
LoadBalancer
Spring Cloud LoadBalancer替代了已停止维护的Netflix
Ribbon,提供客户端负载均衡能力:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class WeightedRandomLoadBalancer implements ReactorServiceInstanceListSupplier { private final ServiceInstanceListSupplier delegate; public WeightedRandomLoadBalancer (ServiceInstanceListSupplier delegate) { this .delegate = delegate; } @Override public Flux<List<ServiceInstance>> get () { return delegate.get().map(this ::selectByWeight); } private List<ServiceInstance> selectByWeight (List<ServiceInstance> instances) { int totalWeight = instances.stream() .mapToInt(inst -> Integer.parseInt( inst.getMetadata().getOrDefault("weight" , "1" ))) .sum(); int random = ThreadLocalRandom.current().nextInt(totalWeight); int current = 0 ; for (ServiceInstance instance : instances) { int weight = Integer.parseInt( instance.getMetadata().getOrDefault("weight" , "1" )); current += weight; if (random < current) { return Collections.singletonList(instance); } } return Collections.singletonList(instances.get(0 )); } @Override public String getServiceId () { return delegate.getServiceId(); } }
熔断降级 - Sentinel
Sentinel是面向分布式服务架构的流量治理组件,提供流量控制、熔断降级、系统自适应保护等功能。
stateDiagram-v2
[*] --> Closed: 初始状态
Closed --> Open: 错误率/慢调用比例超过阈值
Open --> HalfOpen: 熔断时长结束
HalfOpen --> Closed: 探测请求成功
HalfOpen --> Open: 探测请求失败
state Closed {
[*] --> 正常处理请求
正常处理请求 --> 统计异常比例
}
state Open {
[*] --> 拒绝所有请求
拒绝所有请求 --> 执行降级逻辑
}
state HalfOpen {
[*] --> 放行少量探测请求
}
Sentinel规则配置与使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 @RestController @RequestMapping("/api/orders") public class OrderController { private final OrderService orderService; public OrderController (OrderService orderService) { this .orderService = orderService; } @GetMapping("/{id}") @SentinelResource( value = "getOrder", blockHandler = "getOrderBlockHandler", fallback = "getOrderFallback" ) public OrderVO getOrder (@PathVariable Long id) { return orderService.getOrderById(id); } public OrderVO getOrderBlockHandler (Long id, BlockException ex) { throw new ServiceException ("系统繁忙,请稍后重试" ); } public OrderVO getOrderFallback (Long id, Throwable throwable) { return OrderVO.defaultOrder(id); } }@Configuration public class SentinelRuleConfig { @PostConstruct public void initRules () { FlowRule flowRule = new FlowRule (); flowRule.setResource("getOrder" ); flowRule.setGrade(RuleConstant.FLOW_GRADE_QPS); flowRule.setCount(100 ); flowRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); flowRule.setMaxQueueingTimeMs(500 ); FlowRuleManager.loadRules(Collections.singletonList(flowRule)); DegradeRule degradeRule = new DegradeRule (); degradeRule.setResource("getOrder" ); degradeRule.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType()); degradeRule.setCount(0.5 ); degradeRule.setTimeWindow(5 ); degradeRule.setSlowRatioThreshold(0.5 ); degradeRule.setMinRequestAmount(10 ); degradeRule.setStatIntervalMs(10000 ); DegradeRuleManager.loadRules(Collections.singletonList(degradeRule)); } }
API Gateway - Spring Cloud
Gateway
Spring Cloud Gateway是基于Spring
WebFlux构建的API网关,提供路由、过滤、限流等能力。
graph LR
Client[客户端请求] --> Predicate{路由断言匹配}
Predicate -->|匹配成功| PreFilters[前置过滤器链]
Predicate -->|匹配失败| NotFound[404]
PreFilters --> ProxyService[代理到下游服务]
ProxyService --> PostFilters[后置过滤器链]
PostFilters --> Response[返回响应]
subgraph 过滤器链
PreFilters
PostFilters
end
网关路由与过滤器配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 spring: cloud: gateway: routes: - id: user-service uri: lb://user-service predicates: - Path=/api/users/** filters: - StripPrefix=0 - name: CircuitBreaker args: name: userServiceCB fallbackUri: forward:/fallback/user - id: order-service uri: lb://order-service predicates: - Path=/api/orders/** - Method=GET,POST filters: - StripPrefix=0 - AddRequestHeader=X-Request-Source, gateway - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 100 redis-rate-limiter.burstCapacity: 200 key-resolver: "#{@userKeyResolver}"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 @Component @Order(-1) public class AuthGlobalFilter implements GlobalFilter { private static final List<String> WHITE_LIST = List.of( "/api/users/login" , "/api/users/register" , "/health" ); private final JwtUtil jwtUtil; public AuthGlobalFilter (JwtUtil jwtUtil) { this .jwtUtil = jwtUtil; } @Override public Mono<Void> filter (ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getURI().getPath(); if (WHITE_LIST.stream().anyMatch(path::startsWith)) { return chain.filter(exchange); } String token = request.getHeaders().getFirst("Authorization" ); if (token == null || !token.startsWith("Bearer " )) { return unauthorized(exchange, "缺少认证令牌" ); } try { String jwt = token.substring(7 ); Claims claims = jwtUtil.parseToken(jwt); ServerHttpRequest mutatedRequest = request.mutate() .header("X-User-Id" , claims.getSubject()) .header("X-User-Role" , claims.get("role" , String.class)) .build(); return chain.filter(exchange.mutate().request(mutatedRequest).build()); } catch (ExpiredJwtException e) { return unauthorized(exchange, "令牌已过期" ); } catch (JwtException e) { return unauthorized(exchange, "令牌无效" ); } } private Mono<Void> unauthorized (ServerWebExchange exchange, String message) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); response.getHeaders().setContentType(MediaType.APPLICATION_JSON); String body = """ {"code": 401, "message": "%s"} """ .formatted(message); DataBuffer buffer = response.bufferFactory() .wrap(body.getBytes(StandardCharsets.UTF_8)); return response.writeWith(Mono.just(buffer)); } }
配置中心 - Nacos Config
Nacos
Config支持配置的集中管理和动态刷新,无需重启服务即可更新配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 spring: application: name: order-service cloud: nacos: config: server-addr: localhost:8848 namespace: dev group: DEFAULT_GROUP file-extension: yaml shared-configs: - data-id: common-db.yaml group: DEFAULT_GROUP refresh: true - data-id: common-redis.yaml group: DEFAULT_GROUP refresh: true
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @RestController @RefreshScope public class ConfigController { @Value("${order.max-retry-times:3}") private int maxRetryTimes; @Value("${order.timeout-seconds:30}") private int timeoutSeconds; @GetMapping("/config/info") public Map<String, Object> getConfig () { return Map.of( "maxRetryTimes" , maxRetryTimes, "timeoutSeconds" , timeoutSeconds ); } }@Component public class NacosConfigListener { private static final Logger log = LoggerFactory.getLogger(NacosConfigListener.class); @NacosConfigListener(dataId = "order-service.yaml", groupId = "DEFAULT_GROUP") public void onConfigChange (String newConfig) { log.info("检测到配置变更,最新配置内容: {}" , newConfig); } }
分布式链路追踪 - Micrometer
Tracing
Spring Cloud 2023.x 已经用 Micrometer Tracing 取代了 Spring Cloud
Sleuth。通过链路追踪我们可以清晰地看到一个请求在各微服务间的调用链路和耗时。
graph LR
A[Gateway<br/>traceId=abc123] -->|spanId=1| B[Order Service<br/>traceId=abc123]
B -->|spanId=2| C[User Service<br/>traceId=abc123]
B -->|spanId=3| D[Product Service<br/>traceId=abc123]
D -->|spanId=4| E[Inventory Service<br/>traceId=abc123]
style A fill:#e1f5fe
style B fill:#fff3e0
style C fill:#e8f5e9
style D fill:#fce4ec
style E fill:#f3e5f5
1 2 3 4 5 6 7 8 9 10 11 12 management: tracing: sampling: probability: 1.0 zipkin: tracing: endpoint: http://localhost:9411/api/v2/spans logging: pattern: level: "%5p [${spring.application.name},%X{traceId},%X{spanId}]"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @Service public class PaymentService { private final Tracer tracer; private final ObservationRegistry observationRegistry; public PaymentService (Tracer tracer, ObservationRegistry observationRegistry) { this .tracer = tracer; this .observationRegistry = observationRegistry; } public PaymentResult processPayment (PaymentRequest request) { return Observation.createNotStarted("payment.process" , observationRegistry) .lowCardinalityKeyValue("payment.method" , request.getMethod().name()) .observe(() -> { PaymentResult result = callPaymentGateway(request); Span currentSpan = tracer.currentSpan(); if (currentSpan != null ) { currentSpan.tag("payment.orderId" , request.getOrderId()); currentSpan.tag("payment.amount" , request.getAmount().toString()); currentSpan.event("payment.completed" ); } return result; }); } }
最佳实践与注意事项
服务拆分原则
单一职责 :每个服务只负责一个业务领域,避免出现”大服务”。
数据独立 :每个服务拥有独立的数据存储,禁止跨服务直接访问数据库。
接口契约 :服务间通过明确定义的API通信,接口变更需要版本管理。
性能与稳定性建议
Feign超时
连接超时2s,读取超时5s,避免长时间等待
熔断阈值
根据实际QPS调整,生产环境不要使用默认值
线程隔离
对不同的下游服务使用独立线程池,防止线程池耗尽
配置刷新
高频变更的配置使用动态刷新,低频配置重启即可
链路采样率
生产环境设为10%-20%,全量采样会严重影响性能
网关限流
结合Redis实现分布式限流,单机限流在集群环境下不准确
容错设计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 @Service public class ProductService { private final ProductClient productClient; private final RedisTemplate<String, Product> redisTemplate; private final LoadingCache<Long, Product> localCache; public ProductService (ProductClient productClient, RedisTemplate<String, Product> redisTemplate) { this .productClient = productClient; this .redisTemplate = redisTemplate; this .localCache = Caffeine.newBuilder() .maximumSize(1000 ) .expireAfterWrite(Duration.ofMinutes(5 )) .build(this ::loadProduct); } public Product getProduct (Long id) { try { return localCache.get(id); } catch (Exception e) { return Product.defaultProduct(id); } } private Product loadProduct (Long id) { String key = "product:" + id; Product cached = redisTemplate.opsForValue().get(key); if (cached != null ) { return cached; } Product product = productClient.getProduct(id); redisTemplate.opsForValue().set(key, product, Duration.ofMinutes(30 )); return product; } }
总结
本文系统性地介绍了基于Spring Cloud Alibaba的微服务架构核心组件:
Nacos 同时承担服务注册发现与配置管理的职责,简化了基础设施的运维。
Spring Cloud
LoadBalancer 提供客户端负载均衡,支持自定义策略。
Sentinel 实现了流量控制和熔断降级,保障系统在高并发和故障场景下的稳定性。
Spring Cloud
Gateway 作为统一入口,处理认证鉴权、限流和路由分发。
Micrometer
Tracing 实现分布式链路追踪,帮助快速定位跨服务调用的性能瓶颈。
微服务架构并非银弹,它在解决扩展性问题的同时,也引入了分布式系统的固有复杂性——网络不可靠、数据一致性、运维复杂度等。在实际落地时,应根据团队规模和业务复杂度谨慎评估,避免过度拆分。对于中小型项目,模块化的单体应用往往是更务实的起点。