Java工程实践案例分析:微服务架构下的服务治理与优化
Java工程实践案例分析:微服务架构下的服务治理与优化
背景与目标
随着业务复杂度提升,单体应用逐渐拆分为数十个微服务。
本案例以电商订单系统(Order-Service、Inventory-Service、Payment-Service、Notification-Service 为例)落地Spring Cloud Alibaba技术栈,聚焦以下痛点:
- 服务注册发现与服务间调用不稳定
- 配置与路由无法动态调整
- 限流、熔断规则与业务代码耦合
- 全链路灰度发布与可观测性缺失
本文给出可落地的工程级解决方案,所有代码均基于 Spring Boot 3.2 + Spring Cloud 2023 + Nacos 2.3 + Sentinel 1.8 + RocketMQ 5.1。
总体技术架构
层级 | 组件 | 版本 | 作用 |
---|---|---|---|
注册/配置中心 | Nacos | 2.3.0 | 服务注册、配置管理、动态路由 |
熔断限流 | Sentinel | 1.8.6 | 流量控制、熔断降级、热点参数限流 |
消息总线 | RocketMQ | 5.1.4 | 事件驱动、事务消息、顺序消息 |
网关 | Spring Cloud Gateway | 4.1.0 | 统一入口、灰度路由、鉴权 |
观测 | Micrometer + Prometheus + Grafana | 最新 | 指标、链路、告警 |
服务注册与健康检查
Nacos Server启动
docker run -d --name nacos \
-e MODE=standalone \
-e JVM_XMS=512m -e JVM_XMX=512m \
-p 8848:8848 \
nacos/nacos-server:v2.3.0
服务注册示例(Order-Service)
1. 依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2. 配置 application.yml
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
version: v1.0.0
gray: false # 灰度标签
management:
endpoints.web.exposure.include: health,info
endpoint.health.show-details: always
3. 自定义健康检查(库存接口探针)
@Component
public class InventoryHealthIndicator implements HealthIndicator {
@Autowired
private RestTemplate restTemplate;
@Override
public Health health() {
try {
ResponseEntity<String> resp = restTemplate
.getForEntity("http://inventory-service/actuator/health", String.class);
return resp.getStatusCode().is2xxSuccessful() ?
Health.up().withDetail("inventory", "ok").build() :
Health.down().withDetail("inventory", "unreachable").build();
} catch (Exception ex) {
return Health.down(ex).build();
}
}
}
Nacos控制台可查看实例健康状态,实例摘除阈值通过 spring.cloud.nacos.discovery.heart-beat-interval
调整。
动态配置与热刷新
1. 引入Nacos Config
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2. DataId规范
- shared-config:
order-service.yaml
- 环境隔离:
order-service-dev.yaml
3. 代码级动态属性
@RestController
@RefreshScope // 支持热刷新
public class OrderController {
@Value("${order.pay.timeout:30}")
private int payTimeoutSeconds;
@GetMapping("/config/timeout")
public int getTimeout() {
return payTimeoutSeconds;
}
}
Nacos上修改配置后,客户端会收到长轮询推送,无需重启即可生效。
限流、熔断与热点防护
Sentinel 控制台
docker run -d --name sentinel \
-p 8858:8858 \
bladex/sentinel-dashboard:1.8.6
登录 http://localhost:8858
,默认账号 sentinel/sentinel。
1. 注解式资源定义
@Service
public class OrderService {
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlock",
fallback = "createOrderFallback")
public OrderDTO createOrder(CreateOrderRequest req) {
// 业务逻辑
}
public OrderDTO createOrderBlock(CreateOrderRequest req, BlockException ex) {
throw new BizException("Too many requests, please retry later");
}
public OrderDTO createOrderFallback(CreateOrderRequest req, Throwable ex) {
log.error("createOrder failed", ex);
return OrderDTO.error("系统繁忙,请稍后重试");
}
}
2. 规则持久化到Nacos
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: 127.0.0.1:8848
data-id: order-service-sentinel
rule-type: flow
在Nacos中新增JSON格式限流规则:
[
{
"resource": "createOrder",
"limitApp": "default",
"grade": 1,
"count": 200,
"strategy": 0,
"controlBehavior": 0
}
]
重启或规则变更后,Sentinel客户端自动监听到并生效。
灰度发布与路由权重
Spring Cloud Gateway 集成
1. 过滤器工厂
@Bean
public RouteLocator grayRoute(RouteLocatorBuilder builder) {
return builder.routes()
.route("order-gray", r -> r.path("/api/v1/order/**")
.and().weight("order-service", 90) // 90%流量到v1
.uri("lb://order-service"))
.route("order-gray-v2", r -> r.path("/api/v1/order/**")
.and().weight("order-service", 10) // 10%流量到v2
.and().header("X-Gray", "true")
.uri("lb://order-service-v2"))
.build();
}
2. 自定义元数据匹配
public class GrayVersionPredicate implements Predicate<ServerWebExchange> {
@Override
public boolean test(ServerWebExchange exchange) {
List<ServiceInstance> instances = discoveryClient.getInstances("order-service");
String version = exchange.getRequest().getHeaders().getFirst("X-Version");
return instances.stream()
.anyMatch(i -> version.equals(i.getMetadata().get("version")));
}
}
通过HTTP头 X-Version: v2.0.0
定向到灰度实例。
分布式链路追踪
1. 引入 Micrometer & OpenTelemetry
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
2. 配置
management:
tracing:
sampling:
probability: 0.1
otlp:
endpoint: http://jaeger:4317
3. 自定义Span
@RestController
public class OrderController {
private final Tracer tracer;
@GetMapping("/order/{id}")
public OrderDTO getOrder(@PathVariable Long id) {
Span span = tracer.nextSpan()
.name("queryOrder")
.tag("order.id", id.toString())
.start();
try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
return orderService.findById(id);
} finally {
span.end();
}
}
}
Jaeger UI展示跨服务耗时、异常栈。
性能优化:批量消息与事务消息
订单创建流程:
Order-Service → Inventory-Service(扣减库存) → Payment-Service(预支付) → Notification-Service(通知)
1. RocketMQ事务消息
@Component
public class OrderCreateProducer {
@Autowired
private RocketMQTemplate rocketMQTemplate;
public void sendTransactionMsg(CreateOrderRequest req) {
Message<CreateOrderRequest> msg = MessageBuilder
.withPayload(req)
.setHeader(RocketMQHeaders.TRANSACTION_ID, UUID.randomUUID().toString())
.build();
rocketMQTemplate.sendMessageInTransaction(
"order-topic", msg, null);
}
@RocketMQTransactionListener
static class OrderTransactionListener implements RocketMQLocalTransactionListener {
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
try {
orderService.createOrder((CreateOrderRequest) msg.getPayload());
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
return RocketMQLocalTransactionState.ROLLBACK;
}
}
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
String txId = msg.getHeaders().get(RocketMQHeaders.TRANSACTION_ID, String.class);
return orderService.txExists(txId) ?
RocketMQLocalTransactionState.COMMIT :
RocketMQLocalTransactionState.ROLLBACK;
}
}
}
事务消息保证“创建订单”与“扣减库存”最终一致。
2. 批量消费减少网络RTT
rocketmq:
consumer:
pull-batch-size: 32
Inventory-Service批量处理库存扣减,TPS提升 3.2 倍。
落地经验与踩坑
- Nacos长连接超时
高并发场景下,增加-Dnacos.remote.client.grpc.pool.size=100
。 - Sentinel规则推送延迟
使用 Nacos 持久化时,确保spring.cloud.sentinel.eager=true
,避免懒加载。 - Gateway内存泄漏
开启spring.cloud.gateway.redis-rate-limiter
时,必须设置maxIdle=8
,防止 Lettuce 连接堆积。 - RocketMQ顺序消息性能
将订单号哈希取模到不同队列,避免单队列热点。
- 点赞
- 收藏
- 关注作者
评论(0)