GitHub_Trending Project-Ideas:微服务架构项目解析

GitHub_Trending Project-Ideas:微服务架构项目解析

【免费下载链接】Project-Ideas-And-Resources A Collection of application ideas that can be used to improve your coding skills ❤. 【免费下载链接】Project-Ideas-And-Resources 项目地址: https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources

你还在单体架构的泥潭中挣扎吗?

当你的项目遇到这些困境:

  • 代码库臃肿不堪,新功能开发周期越来越长
  • 团队协作冲突不断,合并代码如同"拆弹"
  • 单一故障点导致整个系统瘫痪
  • 不同模块需要不同技术栈却无法实现
  • 流量高峰时服务器资源浪费严重

本文将通过6个实战维度,带你系统掌握微服务架构设计与实现,从根本上解决以上问题。读完本文你将获得:

  • 微服务架构核心设计原则与评估标准
  • 服务拆分的6种实战模式与决策框架
  • 分布式系统通信的5种方案与代码实现
  • 服务治理全流程解决方案(注册/发现/熔断/限流)
  • 3个企业级微服务项目模板(含代码)
  • DevOps与容器化部署最佳实践

一、微服务架构基础:从理论到实践

1.1 微服务定义与演进

微服务(Microservices)是一种架构风格,它将应用程序构建为一系列小型、自治的服务,每个服务围绕特定业务能力构建,通过轻量级机制通信。

mermaid

1.2 微服务与单体架构对比

特性微服务架构单体架构
代码组织多个小型代码库单一代码库
部署单元独立部署整体部署
技术栈多样化选择统一技术栈
扩展性按需独立扩展整体扩展
故障影响局部影响整体影响
开发效率初期低,后期高初期高,后期低
团队协作自治团队,并行开发集中式团队
学习曲线陡峭平缓

1.3 微服务成熟度评估矩阵

mermaid

微服务就绪度评分表(满分100分):

评估维度评分标准权重
业务复杂度领域边界清晰程度30%
团队结构康威定律匹配度25%
技术能力分布式系统经验20%
运维水平DevOps成熟度15%
业务增长扩展需求迫切性10%

二、微服务架构设计核心原则

2.1 领域驱动设计(DDD)实践

核心概念映射

DDD概念微服务实现
领域(Domain)业务域
限界上下文(Bounded Context)微服务边界
聚合(Aggregate)服务内部数据模型
领域事件(Domain Event)服务间通信事件
领域服务(Domain Service)微服务API

事件风暴工作坊流程

mermaid

2.2 微服务拆分策略与模式

六种拆分模式对比

拆分模式适用场景优点挑战
按业务能力拆分业务边界清晰场景符合业务演进初期划分困难
按子域拆分大型复杂业务系统与DDD高度契合需资深领域专家
按数据拆分数据密集型应用数据隔离性好分布式事务复杂
按技术层次拆分技术栈差异大的系统技术自由度高易形成分布式单体
按团队拆分大型团队协作符合康威定律可能导致服务粒度不均
渐进式拆分单体系统迁移风险可控需要过渡方案

拆分决策框架

mermaid

2.3 服务粒度设计指南

DORA指标与服务粒度关系

服务数量区间部署频率变更失败率恢复时间适合团队规模
1-5个服务每周1-2次<5%<1小时小型团队(1-5人)
6-20个服务每天1-2次5-10%1-4小时中型团队(6-20人)
21-50个服务每天多次10-15%4-8小时大型团队(21-50人)
50+个服务持续部署15-20%8-24小时超大型团队(50+人)

服务粒度检查清单

  • 代码量:单个服务代码量控制在1-10万行
  • 团队规模:"两个披萨团队"原则(5-9人)
  • 部署频率:独立部署周期不超过2周
  • 变更影响:变更影响范围不超过2个依赖服务
  • 接口数量:对外API不超过20个核心接口

三、微服务通信模式与实现

3.1 同步通信机制

REST API设计最佳实践

// 用户服务API示例(Node.js)
const express = require('express');
const app = express();
app.use(express.json());

// 资源命名使用复数名词
app.get('/users', async (req, res) => {
  const { page = 1, limit = 20, status } = req.query;
  // 实现分页和过滤逻辑
  const users = await userService.find({ 
    page, 
    limit,
    status 
  });
  
  // 返回HATEOAS链接
  res.json({
    data: users.items,
    pagination: {
      total: users.total,
      page,
      limit,
      pages: Math.ceil(users.total / limit)
    },
    links: {
      self: `${req.protocol}://${req.get('host')}${req.originalUrl}`,
      next: users.hasMore ? `${req.protocol}://${req.get('host')}/users?page=${page+1}&limit=${limit}` : null
    }
  });
});

// 使用正确的HTTP方法和状态码
app.post('/users', (req, res) => {
  // 验证请求
  const validation = userValidator.validate(req.body);
  if (!validation.isValid) {
    return res.status(400).json({ 
      error: 'VALIDATION_ERROR',
      details: validation.errors 
    });
  }
  
  // 创建用户
  const user = userService.create(req.body);
  return res.status(201).json(user);
});

app.listen(3000);

GraphQL API实现(与微服务集成):

// 产品服务GraphQL模式定义
const typeDefs = gql`
  type Product {
    id: ID!
    name: String!
    price: Float!
    stock: Int!
    category: Category
    reviews: [Review]
  }
  
  type Category {
    id: ID!
    name: String!
    products: [Product]
  }
  
  type Query {
    product(id: ID!): Product
    products(category: ID, page: Int, limit: Int): ProductConnection
  }
  
  type ProductConnection {
    edges: [ProductEdge]
    pageInfo: PageInfo
  }
  
  type ProductEdge {
    node: Product
    cursor: String
  }
  
  type PageInfo {
    hasNextPage: Boolean
    endCursor: String
  }
`;

// 解析器实现(集成其他微服务)
const resolvers = {
  Product: {
    // 跨服务获取评论数据
    async reviews(product) {
      return await fetchFromService({
        service: 'review-service',
        query: `query Reviews($productId: ID!) {
          reviews(productId: $productId) {
            id
            rating
            comment
            user {
              id
              name
            }
          }
        }`,
        variables: { productId: product.id }
      });
    }
  },
  Query: {
    async product(_, { id }) {
      return await productService.findById(id);
    },
    async products(_, { category, page = 1, limit = 20 }) {
      return await productService.find({ category, page, limit });
    }
  }
};

3.2 异步通信与事件驱动架构

事件驱动架构组件

mermaid

Kafka实现事件通信

// 订单服务 - 事件生产者
const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'order-service',
  brokers: ['kafka-1:9092', 'kafka-2:9092'] // 使用Kafka集群
});

const producer = kafka.producer();

async function initProducer() {
  await producer.connect();
}

// 发布订单创建事件
async function publishOrderCreated(order) {
  try {
    await producer.send({
      topic: 'order-events',
      messages: [
        {
          key: order.id,
          value: JSON.stringify({
            type: 'ORDER_CREATED',
            payload: order,
            metadata: {
              timestamp: new Date().toISOString(),
              service: 'order-service',
              version: '1.0.0'
            }
          }),
          headers: {
            eventType: 'ORDER_CREATED',
            correlationId: order.correlationId
          }
        }
      ]
    });
    console.log(`Order event published: ${order.id}`);
  } catch (error) {
    console.error('Failed to publish event:', error);
    // 实现重试机制或发送到死信队列
    await handleEventPublishFailure(error, order);
  }
}

// 库存服务 - 事件消费者
const consumer = kafka.consumer({ 
  groupId: 'inventory-service-group',
  retry: {
    initialRetryTime: 300,
    maxRetryTime: 3000,
    retries: 5
  }
});

async function initConsumer() {
  await consumer.connect();
  
  await consumer.subscribe({ 
    topic: 'order-events', 
    fromBeginning: false 
  });
  
  await consumer.run({
    eachMessage: async ({ topic, partition, message }) => {
      try {
        const event = JSON.parse(message.value.toString());
        
        // 根据事件类型处理
        switch (event.type) {
          case 'ORDER_CREATED':
            await handleOrderCreated(event.payload);
            break;
          case 'ORDER_CANCELLED':
            await handleOrderCancelled(event.payload);
            break;
          default:
            console.log(`Unknown event type: ${event.type}`);
        }
      } catch (error) {
        console.error('Error processing message:', error);
        // 根据错误类型决定是否抛出(触发重试)
        if (isRetriableError(error)) {
          throw error; // 触发Kafka重试
        } else {
          // 不可重试错误,记录并继续
          await logToErrorQueue(message, error);
        }
      }
    }
  });
}

四、微服务架构核心组件实现

4.1 服务注册与发现

比较与选型

服务发现方案实现方式一致性可用性适用场景
EurekaAP架构最终一致高可用AWS/云环境
ConsulCP架构强一致一般对一致性要求高的环境
etcdCP架构强一致较高Kubernetes环境
ZooKeeperCP架构强一致一般复杂分布式协调
Nacos可配置AP/CP可切换混合部署环境

Spring Cloud服务注册发现实现

// 服务提供者配置(application.yml)
spring:
  application:
    name: order-service
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka-server-1:8761/eureka/,http://eureka-server-2:8762/eureka/
  instance:
    preferIpAddress: true
    lease-renewal-interval-in-seconds: 30 # 心跳间隔
    lease-expiration-duration-in-seconds: 90 # 过期时间

// 服务提供者代码
@SpringBootApplication
@EnableEurekaClient
@RestController
public class OrderServiceApplication {
    
    @GetMapping("/orders/{id}")
    public Order getOrder(@PathVariable String id) {
        // 实现订单查询逻辑
        return orderService.findById(id);
    }
    
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

// 服务消费者代码
@SpringBootApplication
@EnableEurekaClient
@RestController
public class PaymentServiceApplication {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Bean
    @LoadBalanced // 启用负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @GetMapping("/payments/{id}/order")
    public Order getPaymentOrder(@PathVariable String id) {
        // 根据支付ID获取订单ID
        String orderId = paymentService.getOrderId(id);
        
        // 通过服务名调用,而非硬编码URL
        return restTemplate.getForObject(
            "http://order-service/orders/" + orderId, 
            Order.class
        );
    }
    
    public static void main(String[] args) {
        SpringApplication.run(PaymentServiceApplication.class, args);
    }
}

4.2 API网关设计与实现

API网关核心功能

mermaid

Spring Cloud Gateway实现

@Configuration
public class GatewayConfig {

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            // 产品服务路由
            .route("product-service", r -> r.path("/api/products/**")
                .filters(f -> f
                    .rewritePath("/api/(?<segment>.*)", "/${segment}")
                    .addResponseHeader("X-Response-Time", "${responseTime}")
                    .requestRateLimiter(c -> c
                        .setRateLimiter(redisRateLimiter())
                        .setKeyResolver(userKeyResolver())
                    )
                    .circuitBreaker(c -> c
                        .setName("productServiceCircuitBreaker")
                        .setFallbackUri("forward:/fallback/products")
                    )
                )
                .uri("lb://product-service")) // 负载均衡到产品服务
                
            // 用户服务路由
            .route("user-service", r -> r.path("/api/users/**")
                .filters(f -> f
                    .rewritePath("/api/(?<segment>.*)", "/${segment}")
                    .filter(authenticationFilter()) // 自定义认证过滤器
                    .retry(c -> c
                        .setRetries(3)
                        .setStatuses(HttpStatus.SERVICE_UNAVAILABLE)
                    )
                )
                .uri("lb://user-service"))
                
            // 订单服务路由
            .route("order-service", r -> r.path("/api/orders/**")
                .filters(f -> f
                    .rewritePath("/api/(?<segment>.*)", "/${segment}")
                    .addRequestHeader("X-Request-ID", "${randomUUID}")
                    .requestSize(c -> c.setMaxSize(1000000)) // 请求大小限制
                )
                .uri("lb://order-service"))
            .build();
    }
    
    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(10, 20); // 令牌桶限流:稳定10r/s,突发20r/s
    }
    
    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(
            Optional.ofNullable(exchange.getRequest().getHeaders().getFirst("X-User-ID"))
                .orElse(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress())
        );
    }
}

4.3 服务容错与弹性设计

熔断降级实现

// 使用Resilience4j实现熔断降级(Node.js)
const { CircuitBreaker, TimeLimiter, Retry } = require('@resilience4j/circuitbreaker');
const { promisify } = require('util');

// 配置熔断器
const circuitBreaker = new CircuitBreaker({
  failureRateThreshold: 50, // 失败率阈值,超过则打开熔断器
  waitDurationInOpenState: 10000, // 熔断器打开状态持续时间(ms)
  slidingWindowSize: 10, // 滑动窗口大小
  minimumNumberOfCalls: 5, // 最小调用次数
  permittedNumberOfCallsInHalfOpenState: 3 // 半开状态允许的调用次数
});

// 配置超时限制
const timeLimiter = new TimeLimiter({
  timeoutDuration: 3000 // 超时时间(ms)
});

// 配置重试策略
const retry = new Retry({
  maxRetryAttempts: 3, // 最大重试次数
  waitDuration: 1000, // 重试间隔(ms)
  retryExceptions: [TimeoutError, NetworkError], // 需要重试的异常类型
  ignoreExceptions: [ValidationError] // 忽略的异常类型
});

// 包装远程服务调用
async function callPaymentService(paymentDetails) {
  // 创建带超时限制的函数
  const timeLimitedFn = timeLimiter.wrap(() => 
    fetch('http://payment-service/api/payments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(paymentDetails)
    })
    .then(response => {
      if (!response.ok) throw new Error(`HTTP error: ${response.status}`);
      return response.json();
    })
  );
  
  // 创建带重试机制的函数
  const retryableFn = retry.wrap(timeLimitedFn);
  
  // 创建带熔断机制的函数
  const circuitBreakerFn = circuitBreaker.wrap(retryableFn);
  
  try {
    return await circuitBreakerFn();
  } catch (error) {
    // 处理最终异常或熔断器打开状态
    if (error instanceof CircuitBreakerOpenError) {
      console.log('Payment service circuit is open, using fallback');
      // 调用降级方案
      return processWithFallbackPayment(paymentDetails);
    }
    throw error;
  }
}

// 降级方案实现
async function processWithFallbackPayment(paymentDetails) {
  // 实现降级逻辑,如使用备用支付服务或队列
  return await fallbackPaymentQueue.enqueue(paymentDetails);
}

舱壁模式实现

// 使用线程池隔离实现舱壁模式(Java)
@Configuration
public class ThreadPoolConfig {
    
    // 订单服务线程池
    @Bean(name = "orderServiceExecutor")
    public Executor orderServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5); // 核心线程数
        executor.setMaxPoolSize(10); // 最大线程数
        executor.setQueueCapacity(20); // 队列容量
        executor.setThreadNamePrefix("order-service-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    // 支付服务线程池
    @Bean(name = "paymentServiceExecutor")
    public Executor paymentServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(6);
        executor.setQueueCapacity(10);
        executor.setThreadNamePrefix("payment-service-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    
    // 库存服务线程池
    @Bean(name = "inventoryServiceExecutor")
    public Executor inventoryServiceExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setQueueCapacity(15);
        executor.setThreadNamePrefix("inventory-service-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
}

// 使用舱壁模式调用外部服务
@Service
public class OrderProcessingService {
    
    private final RestTemplate restTemplate;
    
    @Autowired
    public OrderProcessingService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    
    // 使用订单服务线程池
    @Async("orderServiceExecutor")
    public CompletableFuture<OrderResponse> processOrder(OrderRequest request) {
        // 处理订单逻辑
        return CompletableFuture.completedFuture(new OrderResponse(request.getId()));
    }
    
    // 使用支付服务线程池
    @Async("paymentServiceExecutor")
    public CompletableFuture<PaymentResponse> processPayment(PaymentRequest request) {
        try {
            return CompletableFuture.supplyAsync(() -> 
                restTemplate.postForObject(
                    "http://payment-service/api/payments", 
                    request, 
                    PaymentResponse.class
                )
            );
        } catch (Exception e) {
            throw new ServiceException("Payment service error", e);
        }
    }
    
    // 使用库存服务线程池
    @Async("inventoryServiceExecutor")
    public CompletableFuture<InventoryResponse> checkInventory(InventoryRequest request) {
        try {
            return CompletableFuture.supplyAsync(() -> 
                restTemplate.postForObject(
                    "http://inventory-service/api/inventory/check", 
                    request, 
                    InventoryResponse.class
                )
            );
        } catch (Exception e) {
            throw new ServiceException("Inventory service error", e);
        }
    }
}

五、微服务数据管理

5.1 分布式事务解决方案

事务模式对比

事务模式一致性可用性实现复杂度适用场景
2PC/3PC强一致短事务、关键业务
SAGA最终一致长事务、跨多服务
TCC最终一致核心业务、高性能需求
本地消息表最终一致非实时、低复杂度
事务消息最终一致异步通信场景

SAGA模式实现

// 订单SAGA编排器(Node.js)
class OrderSagaOrchestrator {
  constructor(orderService, paymentService, inventoryService, shippingService) {
    this.orderService = orderService;
    this.paymentService = paymentService;
    this.inventoryService = inventoryService;
    this.shippingService = shippingService;
    this.sagaRepository = new SagaRepository();
  }
  
  // 启动订单SAGA
  async startOrderSaga(orderData) {
    // 创建SAGA实例并记录状态
    const sagaId = uuidv4();
    await this.sagaRepository.createSaga({
      id: sagaId,
      type: 'ORDER_PROCESSING',
      status: 'STARTED',
      data: orderData,
      steps: []
    });
    
    try {
      // 步骤1: 创建订单
      const order = await this.createOrder(sagaId, orderData);
      
      // 步骤2: 扣减库存
      const inventoryResult = await this.reserveInventory(sagaId, order.id, order.items);
      
      // 步骤3: 处理支付
      const paymentResult = await this.processPayment(sagaId, order.id, orderData.payment);
      
      // 步骤4: 创建物流单
      const shippingResult = await this.createShipment(sagaId, order.id, orderData.shipping);
      
      // 完成SAGA
      await this.sagaRepository.updateSagaStatus(sagaId, 'COMPLETED');
      return { success: true, orderId: order.id };
      
    } catch (error) {
      console.error('SAGA failed, initiating compensating transactions', error);
      await this.compensateSaga(sagaId, error);
      throw error;
    }
  }
  
  async createOrder(sagaId, orderData) {
    const stepId = this._generateStepId('CREATE_ORDER');
    await this.sagaRepository.addSagaStep(sagaId, {
      id: stepId,
      action: 'CREATE_ORDER',
      status: 'EXECUTING'
    });
    
    try {
      const order = await this.orderService.createOrder(orderData);
      await this.sagaRepository.updateSagaStep(sagaId, stepId, {
        status: 'COMPLETED',
        result: { orderId: order.id }
      });
      return order;
    } catch (error) {
      await this.sagaRepository.updateSagaStep(sagaId, stepId, {
        status: 'FAILED',
        error: error.message
      });
      throw error;
    }
  }
  
  async reserveInventory(sagaId, orderId, items) {
    const stepId = this._generateStepId('RESERVE_INVENTORY');
    await this.sagaRepository.addSagaStep(sagaId, {
      id: stepId,
      action: 'RESERVE_INVENTORY',
      status: 'EXECUTING'
    });
    
    try {
      const result = await this.inventoryService.reserveItems({
        orderId,
        items: items.map(item => ({
          productId: item.productId,
          quantity: item.quantity
        }))
      });
      
      await this.sagaRepository.updateSagaStep(sagaId, stepId, {
        status: 'COMPLETED',
        result,
        compensationAction: 'RELEASE_INVENTORY',
        compensationData: { reservationId: result.reservationId }
      });
      return result;
    } catch (error) {
      await this.sagaRepository.updateSagaStep(sagaId, stepId, {
        status: 'FAILED',
        error: error.message
      });
      throw error;
    }
  }
  
  // 其他步骤实现...
  
  // 补偿事务
  async compensateSaga(sagaId, error) {
    await this.sagaRepository.updateSagaStatus(sagaId, 'COMPENSATING');
    
    // 获取已完成的步骤,按逆序执行补偿
    const saga = await this.sagaRepository.getSaga(sagaId);
    const completedSteps = saga.steps
      .filter(step => step.status === 'COMPLETED' && step.compensationAction)
      .reverse();
      
    for (const step of completedSteps) {
      try {
        console.log(`Compensating step ${step.action} for saga ${sagaId}`);
        
        switch (step.compensationAction) {
          case 'RELEASE_INVENTORY':
            await this.inventoryService.releaseReservation(step.compensationData.reservationId);
            break;
          case 'REFUND_PAYMENT':
            await this.paymentService.refundPayment(step.compensationData.paymentId);
            break;
          case 'CANCEL_SHIPMENT':
            await this.shippingService.cancelShipment(step.compensationData.shipmentId);
            break;
          case 'DELETE_ORDER':
            await this.orderService.deleteOrder(step.compensationData.orderId);
            break;
        }
        
        await this.sagaRepository.updateSagaStep(sagaId, step.id, {
          compensationStatus: 'COMPLETED'
        });
      } catch (compensationError) {
        console.error(`Compensation failed for step ${step.id}:`, compensationError);
        await this.sagaRepository.updateSagaStep(sagaId, step.id, {
          compensationStatus: 'FAILED',
          compensationError: compensationError.message
        });
        // 记录补偿失败,需要人工干预
        await this.notifyAdminForManualIntervention(sagaId, step, compensationError);
      }
    }
    
    await this.sagaRepository.updateSagaStatus(sagaId, 'COMPENSATED');
  }
  
  // 辅助方法...
}

5.2 CQRS模式实践

CQRS架构实现

// C#实现CQRS架构
// 1. 命令定义
public class CreateProductCommand : ICommand<Guid>
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public int Stock { get; set; }
    public string Category { get; set; }
}

// 2. 命令处理器
public class CreateProductCommandHandler : ICommandHandler<CreateProductCommand, Guid>
{
    private readonly IProductRepository _repository;
    private readonly IEventPublisher _eventPublisher;
    
    public CreateProductCommandHandler(IProductRepository repository, IEventPublisher eventPublisher)
    {
        _repository = repository;
        _eventPublisher = eventPublisher;
    }
    
    public async Task<Guid> Handle(CreateProductCommand command, CancellationToken cancellationToken)
    {
        // 领域逻辑验证
        if (command.Price <= 0)
            throw new ArgumentException("Product price must be greater than zero");
            
        // 创建领域实体
        var product = new Product(
            Guid.NewGuid(),
            command.Name,
            command.Price,
            command.Stock,
            command.Category
        );
        
        // 保存实体
        await _repository.AddAsync(product);
        
        // 发布领域事件
        await _eventPublisher.Publish(new ProductCreatedEvent
        {
            ProductId = product.Id,
            Name = product.Name,
            Price = product.Price,
            Category = product.Category,
            Timestamp = DateTime.UtcNow
        });
        
        return product.Id;
    }
}

// 3. 查询定义
public class GetProductByIdQuery : IQuery<ProductDetailDto>
{
    public Guid ProductId { get; set; }
}

// 4. 查询处理器
public class GetProductByIdQueryHandler : IQueryHandler<GetProductByIdQuery, ProductDetailDto>
{
    private readonly IReadDbContext _readDbContext;
    
    public GetProductByIdQueryHandler(IReadDbContext readDbContext)
    {
        _readDbContext = readDbContext;
    }
    
    public async Task<ProductDetailDto> Handle(GetProductByIdQuery query, CancellationToken cancellationToken)
    {
        // 从只读数据库查询数据
        var product = await _readDbContext.Products
            .Where(p => p.Id == query.ProductId)
            .Select(p => new ProductDetailDto
            {
                Id = p.Id,
                Name = p.Name,
                Price = p.Price,
                Stock = p.Stock,
                Category = p.Category,
                CreatedAt = p.CreatedAt,
                LastUpdated = p.LastUpdated
            })
            .FirstOrDefaultAsync(cancellationToken);
            
        if (product == null)
            throw new NotFoundException($"Product with ID {query.ProductId} not found");
            
        return product;
    }
}

// 5. 事件处理器(更新读模型)
public class ProductCreatedEventHandler : IEventHandler<ProductCreatedEvent>
{
    private readonly IReadDbContext _readDbContext;
    
    public ProductCreatedEventHandler(IReadDbContext readDbContext)
    {
        _readDbContext = readDbContext;
    }
    
    public async Task Handle(ProductCreatedEvent @event, CancellationToken cancellationToken)
    {
        // 更新读模型
        var productReadModel = new ProductReadModel
        {
            Id = @event.ProductId,
            Name = @event.Name,
            Price = @event.Price,
            Stock = @event.Stock,
            Category = @event.Category,
            CreatedAt = @event.Timestamp,
            LastUpdated = @event.Timestamp
        };
        
        _readDbContext.Products.Add(productReadModel);
        await _readDbContext.SaveChangesAsync(cancellationToken);
    }
}

// 6. API控制器

【免费下载链接】Project-Ideas-And-Resources A Collection of application ideas that can be used to improve your coding skills ❤. 【免费下载链接】Project-Ideas-And-Resources 项目地址: https://gitcode.com/GitHub_Trending/pr/Project-Ideas-And-Resources

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值