← 返回首页
🔧

微服务架构概述

📂 architecture ⏱ 3 min 535 words

微服务架构概述

什么是微服务架构

微服务架构是一种将应用程序构建为一组小型、自治服务的架构模式。每个服务运行在自己的进程中,通过轻量级机制(通常是HTTP API)进行通信。这些服务围绕业务能力组织,可以通过全自动化的部署机制独立部署。

核心原则

单一职责原则

每个微服务只负责一个特定的业务功能。这使得服务更容易理解、开发和维护。

// 订单服务 - 只负责订单相关的业务
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    private final OrderService orderService;
    
    @PostMapping
    public ResponseEntity<OrderDto> createOrder(@RequestBody CreateOrderRequest request) {
        OrderDto order = orderService.createOrder(request);
        return ResponseEntity.ok(order);
    }
}

// 用户服务 - 只负责用户相关的业务
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    private final UserService userService;
    
    @PostMapping
    public ResponseEntity<UserDto> createUser(@RequestBody CreateUserRequest request) {
        UserDto user = userService.createUser(request);
        return ResponseEntity.ok(user);
    }
}

自治性

每个微服务应该能够独立开发、测试、部署和扩展。服务之间通过明确定义的API进行通信。

// 服务间通信 - 使用Feign客户端
@FeignClient(name = "user-service", url = "${user-service.url}")
public interface UserClient {
    
    @GetMapping("/api/users/{id}")
    UserDto getUser(@PathVariable("id") Long id);
    
    @PostMapping("/api/users")
    UserDto createUser(@RequestBody CreateUserRequest request);
}

// 订单服务中使用用户服务
@Service
public class OrderService {
    
    private final UserClient userClient;
    private final OrderRepository orderRepository;
    
    public OrderDto createOrder(CreateOrderRequest request) {
        // 调用用户服务验证用户
        UserDto user = userClient.getUser(request.getUserId());
        if (user == null) {
            throw new UserNotFoundException(request.getUserId());
        }
        
        // 创建订单
        Order order = Order.create(request);
        orderRepository.save(order);
        
        return OrderDto.from(order);
    }
}

去中心化数据管理

每个微服务拥有自己的数据库,服务之间不直接访问对方的数据库。

// 订单服务 - 拥有自己的数据库
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "user_id")
    private Long userId;  // 只存储用户ID,不存储用户详细信息
    
    // 其他订单相关字段
}

// 用户服务 - 拥有自己的数据库
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue
    private Long id;
    
    private String name;
    private String email;
    
    // 其他用户相关字段
}

服务拆分策略

按业务能力拆分

根据业务能力将系统拆分为不同的服务。这是最常见的拆分策略。

电商平台
├── 用户服务 (User Service)
│   ├── 用户注册
│   ├── 用户认证
│   └── 用户信息管理
├── 商品服务 (Product Service)
│   ├── 商品目录
│   ├── 商品搜索
│   └── 库存管理
├── 订单服务 (Order Service)
│   ├── 订单创建
│   ├── 订单处理
│   └── 订单状态管理
├── 支付服务 (Payment Service)
│   ├── 支付处理
│   ├── 退款处理
│   └── 支付记录
└── 通知服务 (Notification Service)
    ├── 邮件通知
    ├── 短信通知
    └── 推送通知

按子域拆分

使用领域驱动设计(DDD)的概念,根据限界上下文进行拆分。

// 上下文映射示例
// 订单上下文
package com.example.order.context;

public class Order {
    // 订单上下文中的订单实体
    private OrderId id;
    private CustomerId customerId;  // 引用用户上下文的ID
    private List<OrderItem> items;
}

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

public class Customer {
    // 用户上下文中的客户实体
    private CustomerId id;
    private String name;
    private String email;
}

关键技术挑战

服务发现

微服务需要能够发现彼此的位置。

// 使用Consul进行服务发现
@Component
public class ServiceDiscovery {
    
    private final ConsulClient consulClient;
    
    public String getServiceUrl(String serviceName) {
        HealthService healthService = consulClient.getHealthService(serviceName);
        if (healthService != null && !healthService.getChecks().isEmpty()) {
            ServiceEntry entry = healthService.getService();
            return String.format("http://%s:%d", 
                entry.getAddress(), 
                entry.getPort());
        }
        throw new ServiceNotFoundException(serviceName);
    }
}

// 使用Eureka进行服务发现
@FeignClient(name = "user-service")
public interface UserClient {
    // Spring Cloud会自动使用Eureka进行服务发现
    @GetMapping("/api/users/{id}")
    UserDto getUser(@PathVariable("id") Long id);
}

负载均衡

在多个服务实例之间分配请求。

// 使用Ribbon进行客户端负载均衡
@FeignClient(name = "user-service")
@RibbonClient(name = "user-service")
public interface UserClient {
    @GetMapping("/api/users/{id}")
    UserDto getUser(@PathVariable("id") Long id);
}

// 配置负载均衡策略
@Configuration
public class RibbonConfiguration {
    
    @Bean
    public IRule ribbonRule() {
        // 使用轮询策略
        return new RoundRobinRule();
        // 或者使用随机策略
        // return new RandomRule();
        // 或者使用重试策略
        // return new RetryRule();
    }
}

熔断器

防止级联故障,当服务不可用时快速失败。

// 使用Hystrix实现熔断器
@Component
public class UserServiceClient {
    
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public UserDto getUser(Long userId) {
        return restTemplate.getForObject(
            "http://user-service/api/users/{id}", 
            UserDto.class, 
            userId
        );
    }
    
    public UserDto getUserFallback(Long userId) {
        // 降级逻辑
        return new UserDto(userId, "Unknown User", "unknown@example.com");
    }
}

// 使用Resilience4j实现熔断器
@Component
public class UserServiceClient {
    
    @CircuitBreaker(name = "userService", fallbackMethod = "getUserFallback")
    public UserDto getUser(Long userId) {
        return restTemplate.getForObject(
            "http://user-service/api/users/{id}", 
            UserDto.class, 
            userId
        );
    }
    
    public UserDto getUserFallback(Long userId, Exception e) {
        // 降级逻辑
        return new UserDto(userId, "Unknown User", "unknown@example.com");
    }
}

微服务架构的优点

  1. 技术异构性:不同服务可以使用不同的技术栈
  2. 独立部署:每个服务可以独立部署,不影响其他服务
  3. 可扩展性:可以针对特定服务进行独立扩展
  4. 容错性:单个服务故障不会影响整个系统
  5. 团队自治:不同团队可以独立开发和维护自己的服务

微服务架构的挑战

  1. 分布式系统复杂性:需要处理网络延迟、分区容错等问题
  2. 数据一致性:跨服务的数据一致性难以保证
  3. 运维复杂性:需要管理大量的服务和基础设施
  4. 测试复杂性:集成测试和端到端测试变得更加困难
  5. 监控和日志:需要集中化的监控和日志管理

实施建议

  1. 从单体开始:不要一开始就设计微服务,先构建单体,再逐步拆分
  2. 定义清晰的API:服务间通信应该通过明确定义的API
  3. 实现自动化:建立自动化构建、测试和部署流水线
  4. 建立监控体系:监控服务健康状况、性能指标和业务指标
  5. 使用容器化:使用Docker和Kubernetes进行服务部署和管理