当前位置:首页 > 学习笔记 > 正文内容

微服务架构完全指南:分布式系统设计的核心实践

廖万里12小时前学习笔记1
微服务架构完全指南
"微服务架构是一种将单一应用程序划分成一组小服务的方法,每个服务运行在独立的进程中,服务间通过轻量级通信机制协作。这种架构模式让大型复杂应用的开发、部署和扩展变得更加灵活。"

一、微服务架构核心概念

微服务架构自2014年由Martin Fowler正式提出以来,已经成为企业级应用架构的主流选择。与传统的单体架构相比,微服务将应用拆分为多个独立的小服务,每个服务专注于特定的业务功能,可以独立开发、测试、部署和扩展。

单体架构 vs 微服务架构

单体架构将所有功能模块打包在同一个应用中,虽然开发和部署简单,但随着业务增长,代码库变得庞大臃肿,技术栈难以升级,部署风险增加。一个小的改动可能需要重新部署整个应用。 微服务架构则将系统按业务领域拆分,每个服务规模适中,团队可以独立开发和部署。技术栈选择更加灵活,可以根据服务特点选择最合适的技术方案。系统容错性更好,单个服务的故障不会导致整个系统崩溃。

微服务的优势与挑战

优势: - 独立部署:每个服务可独立发布,缩短交付周期 - 技术异构:不同服务可使用不同编程语言和数据存储 - 弹性扩展:可针对瓶颈服务单独扩展资源 - 故障隔离:单服务故障不影响整体系统可用性 - 团队自治:小团队独立负责服务全生命周期 挑战: - 分布式复杂性:网络延迟、数据一致性、服务发现等问题 - 运维难度:需要完善的自动化部署和监控体系 - 数据管理:跨服务事务和查询变得复杂 - 测试困难:集成测试和端到端测试难度增加

二、服务拆分策略

合理的服务拆分是微服务架构成功的关键。拆分粒度过细会增加运维复杂度,过粗则无法发挥微服务优势。

领域驱动设计(DDD)

领域驱动设计是指导服务拆分的最佳实践。核心概念包括: 限界上下文(Bounded Context):每个限界上下文对应一个微服务,上下文边界清晰,内部模型完整。 聚合(Aggregate):一组相关对象的集合,作为数据修改的单元。聚合根是聚合的唯一入口。 领域事件:表示领域中发生的事情,用于服务间通信和解耦。
// 订单聚合根
public class Order {
    private OrderId id;
    private CustomerId customerId;
    private List<OrderItem> items;
    private OrderStatus status;
    private Money totalAmount;
    
    // 业务方法保证不变性
    public void addItem(Product product, int quantity) {
        if (status != OrderStatus.DRAFT) {
            throw new IllegalStateException("只能修改草稿订单");
        }
        OrderItem item = new OrderItem(product, quantity);
        items.add(item);
        recalculateTotal();
    }
    
    public void submit() {
        if (items.isEmpty()) {
            throw new IllegalStateException("订单项不能为空");
        }
        status = OrderStatus.SUBMITTED;
        // 发布领域事件
        DomainEventPublisher.publish(new OrderSubmittedEvent(this.id));
    }
}

拆分原则

1. 单一职责:每个服务只负责一个业务能力 2. 高内聚低耦合:服务内部紧密关联,服务间松散耦合 3. 独立数据存储:每个服务拥有独立数据库,避免数据层耦合 4. API稳定:服务接口设计要稳定,版本演进要兼容

三、服务通信机制

微服务间通信主要有两种模式:同步通信(REST/RPC)和异步通信(消息队列)。

同步通信:REST API

REST是最常用的服务间通信方式,简单易懂,与HTTP协议天然契合。
@Service
public class ProductServiceClient {
    private final RestTemplate restTemplate;
    private final String productServiceUrl = "http://product-service/api/products";
    
    public ProductDTO getProduct(Long productId) {
        String url = productServiceUrl + "/" + productId;
        try {
            return restTemplate.getForObject(url, ProductDTO.class);
        } catch (HttpClientErrorException e) {
            if (e.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new ProductNotFoundException(productId);
            }
            throw new ServiceException("产品服务调用失败", e);
        }
    }
}

// 使用OpenFeign简化调用
@FeignClient(name = "product-service", fallback = ProductClientFallback.class)
public interface ProductClient {
    @GetMapping("/api/products/{id}")
    ProductDTO getProduct(@PathVariable Long id);
}

@Component
class ProductClientFallback implements ProductClient {
    @Override
    public ProductDTO getProduct(Long id) {
        // 降级逻辑
        return new ProductDTO(id, "默认产品", BigDecimal.ZERO);
    }
}

异步通信:消息队列

消息队列实现服务间解耦,支持流量削峰和异步处理。
// 订单服务发布事件
@Service
public class OrderService {
    private final KafkaTemplate<String, Object> kafkaTemplate;
    
    public void createOrder(OrderDTO orderDTO) {
        // 创建订单逻辑
        Order order = orderRepository.save(orderDTO);
        
        // 发布订单创建事件
        OrderCreatedEvent event = new OrderCreatedEvent(
            order.getId(),
            order.getCustomerId(),
            order.getTotalAmount()
        );
        kafkaTemplate.send("order-events", order.getId().toString(), event);
    }
}

// 库存服务订阅事件
@Service
public class InventoryService {
    @KafkaListener(topics = "order-events")
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 扣减库存
        for (OrderItemDTO item : event.getItems()) {
            inventoryRepository.deductStock(item.getProductId(), item.getQuantity());
        }
    }
}

四、服务发现与负载均衡

在动态的微服务环境中,服务实例的IP地址和端口经常变化,需要服务发现机制来定位服务。

服务注册中心

# Nacos配置
spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: dev
        group: DEFAULT_GROUP
      config:
        server-addr: localhost:8848
        file-extension: yaml

# Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

客户端负载均衡

Spring Cloud LoadBalancer提供客户端负载均衡能力,支持多种负载均衡策略。
@Configuration
public class LoadBalancerConfig {
    
    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
        Environment environment,
        LoadBalancerClientFactory factory
    ) {
        String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(
            factory.getLazyProvider(serviceId, ServiceInstanceListSupplier.class),
            serviceId
        );
    }
}

// 自定义负载均衡策略
public class WeightedLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        // 根据权重选择实例
    }
}

五、API网关

API网关是微服务架构的重要组件,负责请求路由、认证授权、限流熔断等功能。
# Spring Cloud Gateway配置
spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
            - name: JwtAuth
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: CircuitBreaker
              args:
                name: orderCircuitBreaker
                fallbackUri: forward:/fallback/orders

# 自定义过滤器
@Component
public class JwtAuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        
        if (token == null || !jwtUtil.validateToken(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        
        String userId = jwtUtil.extractUserId(token);
        ServerHttpRequest request = exchange.getRequest().mutate()
            .header("X-User-Id", userId)
            .build();
        
        return chain.filter(exchange.mutate().request(request).build());
    }
}

六、分布式事务处理

微服务架构下,跨服务的事务处理是一大挑战。常用的解决方案有2PC、TCC、Saga等。

Saga模式

Saga将分布式事务拆分为多个本地事务,每个本地事务执行后发布事件,触发下一个本地事务。如果某个步骤失败,执行补偿操作。
// 订单创建Saga
@Service
public class CreateOrderSaga {
    
    public void execute(CreateOrderCommand command) {
        // 步骤1:创建订单
        Order order = orderService.create(command);
        
        try {
            // 步骤2:扣减库存
            inventoryService.deductStock(command.getItems());
        } catch (InsufficientStockException e) {
            // 补偿:取消订单
            orderService.cancel(order.getId());
            throw e;
        }
        
        try {
            // 步骤3:扣减余额
            paymentService.deductBalance(command.getCustomerId(), command.getAmount());
        } catch (InsufficientBalanceException e) {
            // 补偿:恢复库存、取消订单
            inventoryService.restoreStock(command.getItems());
            orderService.cancel(order.getId());
            throw e;
        }
        
        // 步骤4:确认订单
        orderService.confirm(order.getId());
    }
}

// 基于事件的Saga编排
@Component
public class OrderSagaOrchestrator {
    
    @SagaStart
    @EventListener
    public void handle(OrderCreatedEvent event) {
        sagaManager.start("create-order", event.getOrderId());
        inventoryClient.deductStock(event.getItems());
    }
    
    @SagaStep(compensateMethod = "compensateStock")
    public void handle(StockDeductedEvent event) {
        paymentClient.deductBalance(event.getCustomerId(), event.getAmount());
    }
    
    @SagaStep(compensateMethod = "compensatePayment")
    public void handle(BalanceDeductedEvent event) {
        orderClient.confirmOrder(event.getOrderId());
    }
    
    @SagaEnd
    public void handle(OrderConfirmedEvent event) {
        sagaManager.complete(event.getOrderId());
    }
}

Seata框架

Seata是阿里巴巴开源的分布式事务解决方案,支持AT、TCC、Saga等多种模式。
// AT模式:最简单,自动补偿
@GlobalTransactional
public void createOrder(OrderDTO orderDTO) {
    orderService.save(orderDTO);
    inventoryService.deduct(orderDTO.getItems());
    paymentService.pay(orderDTO.getCustomerId(), orderDTO.getAmount());
}

// TCC模式:需要实现Try、Confirm、Cancel三个方法
@LocalTCC
public interface InventoryTccService {
    @TwoPhaseBusinessAction(name = "deductStock", 
                           commitMethod = "commit", 
                           rollbackMethod = "rollback")
    boolean deductStock(@BusinessActionContextParameter(paramName = "items") 
                        List<OrderItem> items);
    
    boolean commit(BusinessActionContext context);
    
    boolean rollback(BusinessActionContext context);
}

七、服务容错与降级

分布式系统中,服务故障不可避免。需要实现熔断、降级、限流等容错机制。

熔断器模式

// Resilience4j熔断器
@Configuration
public class CircuitBreakerConfig {
    
    @Bean
    public CircuitBreaker circuitBreaker() {
        CircuitBreakerConfig config = CircuitBreakerConfig.custom()
            .failureRateThreshold(50)
            .waitDurationInOpenState(Duration.ofSeconds(30))
            .permittedNumberOfCallsInHalfOpenState(5)
            .slidingWindowSize(100)
            .build();
        
        return CircuitBreaker.of("orderService", config);
    }
}

@Service
public class OrderService {
    
    private final CircuitBreaker circuitBreaker;
    
    @CircuitBreaker(name = "orderService", fallbackMethod = "fallback")
    public Order getOrder(Long orderId) {
        return orderClient.getOrder(orderId);
    }
    
    public Order fallback(Long orderId, Exception e) {
        log.warn("订单服务不可用,返回默认订单: {}", orderId);
        return Order.defaultOrder();
    }
}

限流策略

// Sentinel限流
@Controller
public class OrderController {
    
    @GetMapping("/orders/{id}")
    @SentinelResource(value = "getOrder", 
                      blockHandler = "handleBlock",
                      fallback = "handleFallback")
    public Order getOrder(@PathVariable Long id) {
        return orderService.findById(id);
    }
    
    public Order handleBlock(Long id, BlockException e) {
        throw new RateLimitException("请求过于频繁,请稍后再试");
    }
    
    public Order handleFallback(Long id, Throwable t) {
        return Order.defaultOrder();
    }
}

// Sentinel规则配置
FlowRule rule = new FlowRule();
rule.setResource("getOrder");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule.setCount(100);  // QPS限制为100
FlowRuleManager.loadRules(Collections.singletonList(rule));

八、配置中心

集中管理配置是实现动态调整和统一管理的关键。
# Nacos配置中心
spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        namespace: dev
        group: DEFAULT_GROUP
        file-extension: yaml
        shared-configs:
          - data-id: common.yaml
            refresh: true
// 动态配置刷新
@RefreshScope
@RestController
public class FeatureController {
    
    @Value("${feature.new-ui.enabled:false}")
    private boolean newUiEnabled;
    
    @Value("${feature.max-order-count:100}")
    private int maxOrderCount;
    
    @GetMapping("/features")
    public Map<String, Object> getFeatures() {
        return Map.of(
            "newUiEnabled", newUiEnabled,
            "maxOrderCount", maxOrderCount
        );
    }
}

九、可观测性

微服务架构需要完善的监控、日志和追踪体系。

分布式追踪

# Spring Cloud Sleuth + Zipkin
spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0
    web:
      client:
        enabled: true

指标监控

// Prometheus指标
@Configuration
public class MetricsConfig {
    
    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return registry -> registry.config()
            .commonTags("application", "order-service")
            .commonTags("region", "cn-east-1");
    }
}

// 自定义指标
@Service
public class OrderMetrics {
    private final Counter orderCounter;
    private final Timer orderProcessTimer;
    
    public OrderMetrics(MeterRegistry registry) {
        this.orderCounter = Counter.builder("orders.created")
            .description("创建的订单总数")
            .tag("type", "normal")
            .register(registry);
        
        this.orderProcessTimer = Timer.builder("orders.process.time")
            .description("订单处理时间")
            .register(registry);
    }
    
    public void recordOrderCreated() {
        orderCounter.increment();
    }
    
    public void recordProcessTime(Runnable task) {
        orderProcessTimer.record(task);
    }
}

总结

微服务架构不是银弹,它解决了单体架构的问题,但也带来了新的复杂性。成功的微服务架构需要: 1. 清晰的服务边界和领域划分 2. 完善的基础设施支持(服务发现、配置中心、消息队列) 3. 可靠的服务通信和容错机制 4. 全面的可观测性体系 5. 成熟的DevOps实践 对于小型项目,单体架构可能更合适。只有当系统复杂度达到一定规模,团队规模需要独立协作时,微服务架构的价值才能充分体现。架构选择应该基于实际需求,而不是盲目追风。

本文链接:https://www.kkkliao.cn/?id=845 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


“微服务架构完全指南:分布式系统设计的核心实践” 的相关文章

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。