跳到主要内容

微服务架构

微服务架构(Microservices Architecture)是一种将应用程序构建为一组小型服务的架构风格,每个服务运行在自己的进程中,通过轻量级机制(通常是 HTTP API)进行通信。

什么是微服务架构?

微服务架构将单体应用拆分为多个独立部署的服务,每个服务:

  • 围绕业务能力构建
  • 独立开发、部署和扩展
  • 使用轻量级通信机制
  • 可以使用不同的技术栈
  • 由小团队负责
┌─────────────────────────────────────────────────────────────────────────────┐
│ API Gateway │
│ (统一入口、认证、限流、路由) │
└─────────────────────────────────────────────────────────────────────────────┘

┌───────────────────────────┼───────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
│ (User Service) │ │ (Order Service) │ │ (Product Service) │
│ │ │ │ │ │
│ ┌───────────────┐ │ │ ┌───────────────┐ │ │ ┌───────────────┐ │
│ │ REST API │ │ │ │ REST API │ │ │ │ REST API │ │
│ ├───────────────┤ │ │ ├───────────────┤ │ │ ├───────────────┤ │
│ │ 业务逻辑层 │ │ │ │ 业务逻辑层 │ │ │ │ 业务逻辑层 │ │
│ ├───────────────┤ │ │ ├───────────────┤ │ │ ├───────────────┤ │
│ │ 数据访问层 │ │ │ │ 数据访问层 │ │ │ │ 数据访问层 │ │
│ └───────┬───────┘ │ │ └───────┬───────┘ │ │ └───────┬───────┘ │
│ │ │ │ │ │ │ │ │
└──────────┼──────────┘ └──────────┼──────────┘ └──────────┼──────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌─────────────────────┐ ┌─────────────────────┐
│ 用户数据库 │ │ 订单数据库 │ │ 商品数据库 │
│ (PostgreSQL) │ │ (MySQL) │ │ (MongoDB) │
└─────────────────────┘ └─────────────────────┘ └─────────────────────┘

微服务的核心特征

1. 服务独立性

每个微服务都是独立的单元,有自己的代码库、数据库和部署流程。

// 用户服务 - 独立部署
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}

// 订单服务 - 独立部署
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}

2. 数据库独立

每个服务拥有自己的数据库,避免共享数据库带来的耦合。

# user-service/application.yml
spring:
datasource:
url: jdbc:postgresql://user-db:5432/userdb
username: user_service
password: ${DB_PASSWORD}

---
# order-service/application.yml
spring:
datasource:
url: jdbc:mysql://order-db:3306/orderdb
username: order_service
password: ${DB_PASSWORD}

3. 轻量级通信

服务间通过 REST API 或消息队列通信。

// 使用 Feign 客户端进行服务间调用
@FeignClient(name = "user-service", fallback = UserClientFallback.class)
public interface UserClient {

@GetMapping("/api/users/{userId}")
UserDTO getUserById(@PathVariable("userId") Long userId);

@GetMapping("/api/users/{userId}/validate")
boolean validateUser(@PathVariable("userId") Long userId);
}

// 熔断降级处理
@Component
public class UserClientFallback implements UserClient {
@Override
public UserDTO getUserById(Long userId) {
// 返回默认用户或缓存数据
return UserDTO.builder()
.id(userId)
.username("unknown")
.build();
}

@Override
public boolean validateUser(Long userId) {
// 默认允许,或根据缓存判断
return true;
}
}

微服务拆分策略

按业务能力拆分

根据业务领域划分服务边界。

电商系统拆分示例:

┌─────────────────────────────────────────────────────────┐
│ 业务能力 │
├─────────────────────────────────────────────────────────┤
│ 用户管理 │ 商品管理 │ 订单管理 │ 支付 │ 物流 │
├───────────┼───────────┼───────────┼───────┼───────────┤
│ 用户服务 │ 商品服务 │ 订单服务 │ 支付 │ 物流服务 │
│ User │ Product │ Order │ 服务 │ Logistics │
│ Service │ Service │ Service │ │ Service │
└───────────┴───────────┴───────────┴───────┴───────────┘

按子域拆分(DDD)

使用领域驱动设计(DDD)识别限界上下文。

// 用户上下文
package com.example.user.domain;

public class User {
private UserId id;
private Username username;
private Email email;
private Password password;

public void changePassword(String oldPassword, String newPassword) {
if (!password.matches(oldPassword)) {
throw new InvalidPasswordException();
}
this.password = Password.of(newPassword);
}
}

// 订单上下文
package com.example.order.domain;

public class Order {
private OrderId id;
private UserId userId; // 只存储用户ID,不直接依赖用户实体
private List<OrderItem> items;
private OrderStatus status;

public void confirm() {
if (status != OrderStatus.PENDING) {
throw new IllegalStateException("只能确认待处理订单");
}
this.status = OrderStatus.CONFIRMED;
}
}

微服务通信模式

同步通信

使用 HTTP/REST 或 gRPC 进行同步调用。

@RestController
@RequestMapping("/api/orders")
public class OrderController {

private final OrderService orderService;
private final UserClient userClient;
private final ProductClient productClient;

@PostMapping
public ResponseEntity<OrderDTO> createOrder(@RequestBody CreateOrderRequest request) {
// 1. 验证用户
UserDTO user = userClient.getUserById(request.getUserId());
if (user == null) {
throw new UserNotFoundException(request.getUserId());
}

// 2. 检查库存
for (OrderItemRequest item : request.getItems()) {
boolean inStock = productClient.checkStock(item.getProductId(), item.getQuantity());
if (!inStock) {
throw new InsufficientStockException(item.getProductId());
}
}

// 3. 创建订单
OrderDTO order = orderService.createOrder(request);

return ResponseEntity.status(HttpStatus.CREATED).body(order);
}
}

异步通信

使用消息队列实现异步解耦。

// 订单服务发送事件
@Service
public class OrderEventPublisher {

private final KafkaTemplate<String, OrderEvent> kafkaTemplate;

public void publishOrderCreated(Order order) {
OrderCreatedEvent event = OrderCreatedEvent.builder()
.orderId(order.getId())
.userId(order.getUserId())
.totalAmount(order.getTotalAmount())
.createdAt(order.getCreatedAt())
.build();

kafkaTemplate.send("order-created", event);
}
}

// 库存服务消费事件
@Component
public class InventoryEventListener {

private final InventoryService inventoryService;

@KafkaListener(topics = "order-created", groupId = "inventory-service")
public void handleOrderCreated(OrderCreatedEvent event) {
// 预留库存
inventoryService.reserveStock(event.getOrderId(), event.getItems());
}

@KafkaListener(topics = "order-cancelled", groupId = "inventory-service")
public void handleOrderCancelled(OrderCancelledEvent event) {
// 释放库存
inventoryService.releaseStock(event.getOrderId());
}
}

服务治理

服务注册与发现

// 服务注册(Eureka 客户端)
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
}
}

// 服务发现(使用负载均衡)
@Service
public class OrderService {

private final LoadBalancerClient loadBalancer;

public UserDTO getUserInfo(Long userId) {
ServiceInstance instance = loadBalancer.choose("user-service");
String url = instance.getUri() + "/api/users/" + userId;

return restTemplate.getForObject(url, UserDTO.class);
}
}

熔断与限流

// 使用 Resilience4j 实现熔断
@Service
public class PaymentService {

private final PaymentClient paymentClient;

@CircuitBreaker(name = "payment", fallbackMethod = "processPaymentFallback")
public PaymentResult processPayment(PaymentRequest request) {
return paymentClient.charge(request);
}

// 熔断后的降级处理
public PaymentResult processPaymentFallback(PaymentRequest request, Exception ex) {
log.warn("支付服务不可用,使用备用方案", ex);
// 记录待处理支付,稍后重试
return PaymentResult.pending(request.getOrderId());
}

// 限流
@RateLimiter(name = "payment")
public PaymentResult processWithRateLimit(PaymentRequest request) {
return processPayment(request);
}
}

分布式事务

Saga 模式

通过本地事务和补偿操作实现最终一致性。

// Saga 编排器
@Service
public class OrderSaga {

private final OrderService orderService;
private final InventoryService inventoryService;
private final PaymentService paymentService;

@Transactional
public void executeCreateOrderSaga(CreateOrderRequest request) {
try {
// 步骤1:创建订单
Order order = orderService.createOrder(request);

// 步骤2:扣减库存
inventoryService.deductStock(order.getItems());

// 步骤3:处理支付
paymentService.charge(order.getPaymentInfo());

// 步骤4:确认订单
orderService.confirmOrder(order.getId());

} catch (Exception e) {
// 触发补偿操作
compensateCreateOrder(request);
throw new SagaExecutionException("订单创建失败", e);
}
}

// 补偿操作
private void compensateCreateOrder(CreateOrderRequest request) {
// 补偿1:恢复库存
inventoryService.restoreStock(request.getItems());

// 补偿2:取消订单
orderService.cancelOrder(request.getOrderId());

// 补偿3:退款(如果已支付)
paymentService.refund(request.getOrderId());
}
}

微服务的优缺点

优点

优点说明
独立部署服务可以独立开发、测试和部署
技术多样性每个服务可以选择最适合的技术栈
可扩展性可以针对热点服务单独扩容
故障隔离单个服务故障不会影响整个系统
团队自治小团队可以独立负责完整服务

缺点

缺点说明
分布式复杂性需要处理网络延迟、故障、一致性等问题
运维成本高需要完善的监控、日志、追踪系统
数据一致性跨服务事务处理复杂
测试困难需要集成测试和服务虚拟化
网络开销服务间通信带来性能损耗

微服务最佳实践

1. 服务粒度

避免过细:                    避免过粗:
┌─────────┐ ┌─────────────────────────┐
│ 用户 │ │ 电商服务 │
├─────────┤ │ 用户 │ 订单 │ 商品 │ 支付 │
│ 用户地址 │ └─────────────────────────┘
├─────────┤
│ 用户偏好 │ 推荐粒度:
└─────────┘ ┌─────────┐ ┌─────────┐
│ 用户服务 │ │ 订单服务 │
└─────────┘ └─────────┘

2. API 版本管理

@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 {
// V1 版本 API
}

@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 {
// V2 版本 API,支持更多功能
}

3. 配置中心

# 使用 Spring Cloud Config
spring:
cloud:
config:
uri: http://config-server:8888
name: user-service
profile: ${SPRING_PROFILES_ACTIVE:dev}
label: main

总结

微服务架构适合大型复杂系统,但需要权衡其带来的复杂性。关键成功因素包括:

  1. 合理的拆分:基于业务能力,避免过度拆分
  2. 完善的治理:服务发现、熔断、限流、监控
  3. 自动化运维:CI/CD、容器化、自动扩缩容
  4. 团队文化:DevOps 文化,团队自治

"微服务不是银弹,它解决了一些问题,但也带来了新的问题。选择微服务前,确保你真的需要它。" —— Martin Fowler

延伸阅读