mcpField
E
enterprise-architecture-patterns

enterprise-architecture-patterns

github.com/manutej开发62527 次安装40 周前更新
代码仓库

关于 enterprise-architecture-patterns

面向系统架构师和开发者的企业架构模式技能,涵盖分布式系统、DDD、事件驱动设计与可扩展应用。提供战略和战术模式及实现示例。

主要功能

  1. 01系统设计基础与扩展性
  2. 02DDD 战略与战术模式
  3. 03事件溯源与 CQRS
  4. 04Saga、API Gateway 与 Service Mesh
  5. 05弹性与故障处理模式

适用场景

  1. 01规划微服务及云原生架构
  2. 02为复杂业务建模并划分上下文
  3. 03设计分布式事务和事件流
  4. 04将单体系统迁移到微服务

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/manutej/luxor-claude-marketplace --skill enterprise-architecture-patterns

安装后在 Claude Code 中输入/enterprise-architecture-patterns确认已加载。

附带文件EXAMPLES.mdREADME.md

详细介绍

企业架构模式

这是一项全面的技能,帮助掌握企业架构模式、分布式系统设计和可扩展应用开发。此技能涵盖用于构建健壮、易维护且可扩展的企业系统的战略模式和战术模式。

何时使用此技能

在以下情况下使用此技能:

  • 为分布式系统设计微服务架构
  • 在复杂业务领域中实施领域驱动设计(DDD)
  • 使用事件溯源和 CQRS 构建事件驱动架构
  • 为分布式事务设计 Saga 模式
  • 实施 API 网关和服务网格架构
  • 对应用进行水平扩展和垂直扩展
  • 构建具备容错能力的弹性系统
  • 将单体应用迁移到微服务
  • 设计多租户 SaaS 架构
  • 实施前端专用后端(BFF)模式
  • 使用事件流构建实时系统
  • 设计云原生应用

核心架构概念

系统设计基础

关注点分离 将系统划分为不同的部分,每个部分处理一个独立的关注点,从而降低耦合度并提高内聚性。

模块化 将系统设计为由独立模块组成的集合,这些模块可以分别开发、测试和部署。

抽象 通过简单接口隐藏复杂的实现细节,使系统更易于理解和修改。

可扩展性维度

  • 水平扩展:添加更多机器/实例
  • 垂直扩展:为现有机器添加更多资源
  • 数据扩展:将数据分区存储到多个存储中
  • 功能扩展:按业务能力拆分

一致性模型

  • 强一致性:所有节点同时看到相同的数据
  • 最终一致性:所有节点最终都会看到相同的数据
  • 因果一致性:相关操作看到一致的状态
  • 读己之写一致性:用户能立即看到自己的更新

CAP 定理 在分布式系统中,三项属性只能保证其中两项:

  • 一致性:所有节点看到相同的数据
  • 可用性:每个请求都能收到响应
  • 分区容错性:系统在网络故障时仍能继续运行

分布式计算谬误

  1. 网络是可靠的
  2. 延迟为零
  3. 带宽是无限的
  4. 网络是安全的
  5. 拓扑不会变化
  6. 只有一位管理员
  7. 传输成本为零
  8. 网络是同质的

领域驱动设计(DDD)

战略设计模式
有界上下文

有界上下文是一个明确的边界,在此范围内,领域模型保持一致且有效。它定义了特定术语、定义和规则适用的范围。

核心原则:

  • 每个有界上下文都有自己的通用语言
  • 上下文内的模型保持一致
  • 跨上下文集成需要进行转换
  • 上下文与业务能力相匹配

实现:

// Example: E-commerce system with multiple bounded contexts

// Sales Context
namespace Sales {
  class Customer {
    customerId: string;
    email: string;
    orderHistory: Order[];

    placeOrder(order: Order): void {
      // Sales-specific logic
    }
  }
}

// Billing Context
namespace Billing {
  class Customer {
    customerId: string;
    paymentMethods: PaymentMethod[];
    invoices: Invoice[];

    processPayment(invoice: Invoice): void {
      // Billing-specific logic
    }
  }
}

// Different models for Customer in different contexts

上下文映射模式:

  1. 共享内核:两个上下文共享领域模型的一个子集

    • 适用场景:团队密切协作
    • 风险:变更会影响多个上下文
  2. 客户-供应商:下游上下文依赖上游上下文

    • 适用场景:存在明确的依赖方向
    • 模式:上游提供定义明确的 API
  3. 遵奉者:下游遵循上游模型

    • 适用场景:上游是外部系统或无法更改
    • 模式:适配外部 API
  4. 防腐层:在上下文之间进行转换

    • 适用场景:保护系统免受遗留系统或外部系统的影响
    • 模式:使用适配器或门面转换模型
  5. 各行其道:上下文完全独立

    • 适用场景:不需要集成
    • 模式:必要时复制功能
  6. 开放主机服务:用于集成的协议定义明确

    • 适用场景:多个使用者需要访问
    • 模式:REST API、GraphQL、gRPC
  7. 发布语言:共享且文档完善的语言

    • 适用场景:存在行业标准
    • 模式:XML 架构、JSON 架构、OpenAPI
通用语言

开发者与领域专家共享的词汇,并在代码、文档和交流中保持一致。

构建通用语言:

// Bad: Generic technical terms
class DataProcessor {
  processData(data: any): void {
    // Unclear what this does in business terms
  }
}

// Good: Business domain terms
class OrderFulfillment {
  fulfillOrder(order: Order): void {
    this.pickItems(order.items);
    this.packForShipment(order);
    this.scheduleDelivery(order);
  }

  private pickItems(items: OrderItem[]): void {
    // Business logic using domain language
  }
}
战术设计模式
实体

具有唯一身份并随时间持续存在的对象,用于追踪连续性和生命周期。

特征:

  • 唯一标识符(ID)
  • 可变状态
  • 生命周期(创建、修改、删除)
  • 根据身份而非属性判断相等性

实现:

class Order {
  private readonly orderId: string;
  private orderItems: OrderItem[];
  private status: OrderStatus;
  private orderDate: Date;
  private customerId: string;

  constructor(orderId: string, customerId: string) {
    this.orderId = orderId;
    this.customerId = customerId;
    this.orderItems = [];
    this.status = OrderStatus.Draft;
    this.orderDate = new Date();
  }

  // Business behavior
  addItem(product: Product, quantity: number): void {
    if (this.status !== OrderStatus.Draft) {
      throw new Error("Cannot modify confirmed order");
    }
    this.orderItems.push(new OrderItem(product, quantity));
  }

  confirm(): void {
    if (this.orderItems.length === 0) {
      throw new Error("Cannot confirm empty order");
    }
    this.status = OrderStatus.Confirmed;
  }

  // Identity-based equality
  equals(other: Order): boolean {
    return this.orderId === other.orderId;
  }
}
值对象

根据属性而非身份定义的不可变对象,用于表示领域中的描述性方面。

特征:

  • 没有唯一标识符
  • 不可变(状态无法更改)
  • 根据所有属性判断相等性
  • 通常按值传递
  • 可以安全共享

实现:

class Money {
  readonly amount: number;
  readonly currency: string;

  constructor(amount: number, currency: string) {
    if (amount < 0) {
      throw new Error("Amount cannot be negative");
    }
    this.amount = amount;
    this.currency = currency;
  }

  // Operations return new instances
  add(other: Money): Money {
    if (this.currency !== other.currency) {
      throw new Error("Cannot add different currencies");
    }
    return new Money(this.amount + other.amount, this.currency);
  }

  multiply(factor: number): Money {
    return new Money(this.amount * factor, this.currency);
  }

  // Value-based equality
  equals(other: Money): boolean {
    return this.amount === other.amount &&
           this.currency === other.currency;
  }
}

class Address {
  readonly street: string;
  readonly city: string;
  readonly state: string;
  readonly zipCode: string;
  readonly country: string;

  constructor(
    street: string,
    city: string,
    state: string,
    zipCode: string,
    country: string
  ) {
    this.street = street;
    this.city = city;
    this.state = state;
    this.zipCode = zipCode;
    this.country = country;
  }

  equals(other: Address): boolean {
    return this.street === other.street &&
           this.city === other.city &&
           this.state === other.state &&
           this.zipCode === other.zipCode &&
           this.country === other.country;
  }
}
聚合

具有明确一致性边界的实体和值对象集群,通过单个根实体进行访问。

核心原则:

  • 一个聚合 = 一个事务边界
  • 外部只能引用聚合根
  • 根实体负责维护所有不变量
  • 小型聚合性能更好
  • 聚合之间采用最终一致性

设计规则:

  1. 在一致性边界中建模真正的不变量
  2. 设计小型聚合
  3. 仅通过身份引用其他聚合
  4. 使用最终一致性更新其他聚合
  5. 使用存储库检索聚合

实现:

// Aggregate Root
class Order {
  private readonly orderId: string;
  private readonly customerId: string; // Reference by ID only
  private orderItems: OrderItem[] = [];
  private shippingAddress: Address;
  private status: OrderStatus;
  private totalAmount: Money;

  constructor(orderId: string, customerId: string, shippingAddress: Address) {
    this.orderId = orderId;
    this.customerId = customerId;
    this.shippingAddress = shippingAddress;
    this.status = OrderStatus.Draft;
    this.totalAmount = new Money(0, "USD");
  }

  // Public methods enforce invariants
  addItem(product: Product, quantity: number): void {
    if (this.status !== OrderStatus.Draft) {
      throw new Error("Cannot modify confirmed order");
    }

    if (quantity <= 0) {
      throw new Error("Quantity must be positive");
    }

    const existingItem = this.findItem(product.id);
    if (existingItem) {
      existingItem.increaseQuantity(quantity);
    } else {
      this.orderItems.push(new OrderItem(product, quantity));
    }

    this.recalculateTotal();
  }

  removeItem(productId: string): void {
    if (this.status !== OrderStatus.Draft) {
      throw new Error("Cannot modify confirmed order");
    }

    this.orderItems = this.orderItems.filter(
      item => item.productId !== productId
    );
    this.recalculateTotal();
  }

  confirm(): void {
    if (this.orderItems.length === 0) {
      throw new Error("Cannot confirm empty order");
    }

    if (!this.shippingAddress) {
      throw new Error("Shipping address required");
    }

    this.status = OrderStatus.Confirmed;
  }

  private recalculateTotal(): void {
    this.totalAmount = this.orderItems.reduce(
      (total, item) => total.add(item.subtotal),
      new Money(0, "USD")
    );
  }

  private findItem(productId: string): OrderItem | undefined {
    return this.orderItems.find(item => item.productId === productId);
  }

  // Getters for read-only access
  get id(): string { return this.orderId; }
  get total(): Money { return this.totalAmount; }
  get items(): readonly OrderItem[] { return this.orderItems; }
}

// Entity within aggregate
class OrderItem {
  readonly productId: string;
  readonly productName: string;
  readonly unitPrice: Money;
  private quantity: number;

  constructor(product: Product, quantity: number) {
    this.productId = product.id;
    this.productName = product.name;
    this.unitPrice = product.price;
    this.quantity = quantity;
  }

  increaseQuantity(amount: number): void {
    this.quantity += amount;
  }

  get subtotal(): Money {
    return this.unitPrice.multiply(this.quantity);
  }
}
领域事件

表示领域中发生的重要事件,用于实现松耦合和最终一致性。

特征:

  • 使用过去时命名(OrderPlaced、PaymentProcessed)
  • 不可变
  • 包含所有必要信息
  • 带有时间戳
  • 通常包含聚合 ID

实现:

interface DomainEvent {
  eventId: string;
  occurredAt: Date;
  aggregateId: string;
  eventType: string;
}

class OrderPlacedEvent implements DomainEvent {
  readonly eventId: string;
  readonly occurredAt: Date;
  readonly aggregateId: string;
  readonly eventType = "OrderPlaced";

  readonly orderId: string;
  readonly customerId: string;
  readonly totalAmount: Money;
  readonly items: OrderItemDto[];

  constructor(order: Order) {
    this.eventId = generateId();
    this.occurredAt = new Date();
    this.aggregateId = order.id;
    this.orderId = order.id;
    this.customerId = order.customerId;
    this.totalAmount = order.total;
    this.items = order.items.map(item => ({
      productId: item.productId,
      quantity: item.quantity,
      price: item.unitPrice
    }));
  }
}

// Domain event publisher
class DomainEventPublisher {
  private handlers: Map<string, Function[]> = new Map();

  subscribe(eventType: string, handler: Function): void {
    if (!this.handlers.has(eventType)) {
      this.handlers.set(eventType, []);
    }
    this.handlers.get(eventType)!.push(handler);
  }

  async publish(event: DomainEvent): Promise<void> {
    const handlers = this.handlers.get(event.eventType) || [];
    await Promise.all(handlers.map(handler => handler(event)));
  }
}

// Usage
class OrderService {
  constructor(
    private orderRepository: OrderRepository,
    private eventPublisher: DomainEventPublisher
  ) {}

  async placeOrder(order: Order): Promise<void> {
    order.confirm();
    await this.orderRepository.save(order);

    const event = new OrderPlacedEvent(order);
    await this.eventPublisher.publish(event);
  }
}
存储库

用于访问聚合的抽象,提供类似集合的接口,同时隐藏持久化细节。

原则:

  • 每个聚合根对应一个存储库
  • 面向集合的接口
  • 隐藏数据库实现
  • 返回完整构建的聚合
  • 支持按 ID 和业务条件查询

实现:

interface OrderRepository {
  save(order: Order): Promise<void>;
  findById(orderId: string): Promise<Order | null>;
  findByCustomer(customerId: string): Promise<Order[]>;
  findByStatus(status: OrderStatus): Promise<Order[]>;
  delete(orderId: string): Promise<void>;
}

class OrderRepositoryImpl implements OrderRepository {
  constructor(private db: Database) {}

  async save(order: Order): Promise<void> {
    const data = this.toDataModel(order);
    await this.db.orders.upsert(data);
  }

  async findById(orderId: string): Promise<Order | null> {
    const data = await this.db.orders.findOne({ id: orderId });
    if (!data) return null;
    return this.toDomainModel(data);
  }

  async findByCustomer(customerId: string): Promise<Order[]> {
    const results = await this.db.orders.find({ customerId });
    return results.map(data => this.toDomainModel(data));
  }

  async findByStatus(status: OrderStatus): Promise<Order[]> {
    const results = await this.db.orders.find({ status });
    return results.map(data => this.toDomainModel(data));
  }

  async delete(orderId: string): Promise<void> {
    await this.db.orders.delete({ id: orderId });
  }

  private toDataModel(order: Order): any {
    // Convert domain model to database model
    return {
      id: order.id,
      customerId: order.customerId,
      items: order.items.map(item => ({
        productId: item.productId,
        quantity: item.quantity,
        price: item.unitPrice.amount
      })),
      total: order.total.amount,
      status: order.status
    };
  }

  private toDomainModel(data: any): Order {
    // Reconstruct domain model from database data
    const order = new Order(data.id, data.customerId, data.shippingAddress);
    // Restore items and state
    return order;
  }
}
领域服务

不自然归属于任何实体或值对象的操作,用于封装涉及多个聚合的领域逻辑。

适用场景:

  • 逻辑跨越多个聚合
  • 操作是重要的领域概念
  • 行为无法自然归入实体或值对象

实现:

class PricingService {
  calculateOrderTotal(
    items: OrderItem[],
    customer: Customer,
    promotions: Promotion[]
  ): Money {
    let total = items.reduce(
      (sum, item) => sum.add(item.subtotal),
      new Money(0, "USD")
    );

    // Apply customer discount
    if (customer.isPremium) {
      total = total.multiply(0.9); // 10% discount
    }

    // Apply promotions
    for (const promo of promotions) {
      total = promo.apply(total);
    }

    return total;
  }
}

class TransferService {
  transfer(
    fromAccount: Account,
    toAccount: Account,
    amount: Money
  ): void {
    if (!fromAccount.canWithdraw(amount)) {
      throw new Error("Insufficient funds");
    }

    fromAccount.withdraw(amount);
    toAccount.deposit(amount);
  }
}

事件溯源

事件溯源将系统状态持久化为一系列事件,而不是存储当前状态。当前状态通过重放事件得出。

核心概念

事件存储 系统中发生过的所有事件组成的仅追加日志。

事件流 特定聚合的事件序列,按时间排序。

投影 通过处理事件构建的读取模型,针对查询进行优化。

快照 某个时间点的缓存状态,用于避免重放所有事件。

实现
// Event interface
interface Event {
  eventId: string;
  eventType: string;
  aggregateId: string;
  aggregateType: string;
  version: number;
  timestamp: Date;
  data: any;
  metadata?: any;
}

// Account aggregate with event sourcing
class Account {
  private accountId: string;
  private balance: number = 0;
  private isActive: boolean = true;
  private version: number = 0;
  private uncommittedEvents: Event[] = [];

  constructor(accountId: string) {
    this.accountId = accountId;
  }

  // Command handlers
  open(initialBalance: number): void {
    if (this.version > 0) {
      throw new Error("Account already opened");
    }
    this.applyEvent({
      eventType: "AccountOpened",
      data: { accountId: this.accountId, initialBalance }
    });
  }

  deposit(amount: number): void {
    if (!this.isActive) {
      throw new Error("Account is closed");
    }
    if (amount <= 0) {
      throw new Error("Amount must be positive");
    }
    this.applyEvent({
      eventType: "MoneyDeposited",
      data: { amount }
    });
  }

  withdraw(amount: number): void {
    if (!this.isActive) {
      throw new Error("Account is closed");
    }
    if (amount <= 0) {
      throw new Error("Amount must be positive");
    }
    if (this.balance < amount) {
      throw new Error("Insufficient funds");
    }
    this.applyEvent({
      eventType: "MoneyWithdrawn",
      data: { amount }
    });
  }

  close(): void {
    if (!this.isActive) {
      throw new Error("Account already closed");
    }
    if (this.balance > 0) {
      throw new Error("Cannot close account with positive balance");
    }
    this.applyEvent({
      eventType: "AccountClosed",
      data: {}
    });
  }

  // Event application
  private applyEvent(eventData: Partial<Event>): void {
    const event: Event = {
      eventId: generateId(),
      eventType: eventData.eventType!,
      aggregateId: this.accountId,
      aggregateType: "Account",
      version: this.version + 1,
      timestamp: new Date(),
      data: eventData.data,
      metadata: eventData.metadata
    };

    this.apply(event);
    this.uncommittedEvents.push(event);
  }

  // Event handlers (state mutations)
  private apply(event: Event): void {
    switch (event.eventType) {
      case "AccountOpened":
        this.balance = event.data.initialBalance;
        this.isActive = true;
        break;

      case "MoneyDeposited":
        this.balance += event.data.amount;
        break;

      case "MoneyWithdrawn":
        this.balance -= event.data.amount;
        break;

      case "AccountClosed":
        this.isActive = false;
        break;

      default:
        throw new Error(`Unknown event type: ${event.eventType}`);
    }

    this.version = event.version;
  }

  // Replay events to rebuild state
  static fromEvents(events: Event[]): Account {
    if (events.length === 0) {
      throw new Error("Cannot create account from empty event stream");
    }

    const account = new Account(events[0].aggregateId);
    events.forEach(event => account.apply(event));
    return account;
  }

  getUncommittedEvents(): Event[] {
    return this.uncommittedEvents;
  }

  markEventsAsCommitted(): void {
    this.uncommittedEvents = [];
  }
}

// Event store interface
interface EventStore {
  append(events: Event[]): Promise<void>;
  getEvents(aggregateId: string, fromVersion?: number): Promise<Event[]>;
  getAllEvents(fromTimestamp?: Date): Promise<Event[]>;
}

// Event store implementation
class InMemoryEventStore implements EventStore {
  private events: Map<string, Event[]> = new Map();
  private allEvents: Event[] = [];

  async append(events: Event[]): Promise<void> {
    for (const event of events) {
      // Store in aggregate stream
      if (!this.events.has(event.aggregateId)) {
        this.events.set(event.aggregateId, []);
      }
      this.events.get(event.aggregateId)!.push(event);

      // Store in global stream
      this.allEvents.push(event);
    }
  }

  async getEvents(
    aggregateId: string,
    fromVersion: number = 0
  ): Promise<Event[]> {
    const events = this.events.get(aggregateId) || [];
    return events.filter(e => e.version > fromVersion);
  }

  async getAllEvents(fromTimestamp?: Date): Promise<Event[]> {
    if (!fromTimestamp) {
      return this.allEvents;
    }
    return this.allEvents.filter(e => e.timestamp >= fromTimestamp);
  }
}

// Repository with event sourcing
class EventSourcedAccountRepository {
  constructor(private eventStore: EventStore) {}

  async save(account: Account): Promise<void> {
    const events = account.getUncommittedEvents();
    if (events.length > 0) {
      await this.eventStore.append(events);
      account.markEventsAsCommitted();
    }
  }

  async findById(accountId: string): Promise<Account | null> {
    const events = await this.eventStore.getEvents(accountId);
    if (events.length === 0) {
      return null;
    }
    return Account.fromEvents(events);
  }
}
快照

定期保存聚合状态以优化性能:

interface Snapshot {
  aggregateId: string;
  version: number;
  timestamp: Date;
  state: any;
}

class SnapshotStore {
  private snapshots: Map<string, Snapshot> = new Map();

  async save(snapshot: Snapshot): Promise<void> {
    this.snapshots.set(snapshot.aggregateId, snapshot);
  }

  async getLatest(aggregateId: string): Promise<Snapshot | null> {
    return this.snapshots.get(aggregateId) || null;
  }
}

class EventSourcedAccountRepositoryWithSnapshots {
  constructor(
    private eventStore: EventStore,
    private snapshotStore: SnapshotStore,
    private snapshotInterval: number = 100
  ) {}

  async save(account: Account): Promise<void> {
    const events = account.getUncommittedEvents();
    await this.eventStore.append(events);
    account.markEventsAsCommitted();

    // Create snapshot every N events
    if (account.version % this.snapshotInterval === 0) {
      await this.snapshotStore.save({
        aggregateId: account.id,
        version: account.version,
        timestamp: new Date(),
        state: account.toSnapshot()
      });
    }
  }

  async findById(accountId: string): Promise<Account | null> {
    // Try to load from snapshot
    const snapshot = await this.snapshotStore.getLatest(accountId);
    let account: Account;
    let fromVersion = 0;

    if (snapshot) {
      account = Account.fromSnapshot(snapshot.state);
      fromVersion = snapshot.version;
    } else {
      account = new Account(accountId);
    }

    // Apply events after snapshot
    const events = await this.eventStore.getEvents(accountId, fromVersion);
    events.forEach(event => account.apply(event));

    return account;
  }
}

CQRS(命令查询职责分离)

将读写操作分离到不同的模型中,针对各自的特定用例进行优化。

架构
Commands → Command Handlers → Aggregates → Events → Event Store
                                                   ↓
                                              Event Bus
                                                   ↓
                                           Projections → Read Models → Queries
实现
// Commands (write operations)
interface Command {
  commandId: string;
  timestamp: Date;
}

class CreateAccountCommand implements Command {
  commandId: string;
  timestamp: Date;
  accountId: string;
  initialBalance: number;

  constructor(accountId: string, initialBalance: number) {
    this.commandId = generateId();
    this.timestamp = new Date();
    this.accountId = accountId;
    this.initialBalance = initialBalance;
  }
}

class DepositMoneyCommand implements Command {
  commandId: string;
  timestamp: Date;
  accountId: string;
  amount: number;

  constructor(accountId: string, amount: number) {
    this.commandId = generateId();
    this.timestamp = new Date();
    this.accountId = accountId;
    this.amount = amount;
  }
}

// Command handlers
class AccountCommandHandler {
  constructor(
    private repository: EventSourcedAccountRepository,
    private eventBus: EventBus
  ) {}

  async handle(command: Command): Promise<void> {
    if (command instanceof CreateAccountCommand) {
      await this.handleCreateAccount(command);
    } else if (command instanceof DepositMoneyCommand) {
      await this.handleDepositMoney(command);
    }
  }

  private async handleCreateAccount(
    command: CreateAccountCommand
  ): Promise<void> {
    const account = new Account(command.accountId);
    account.open(command.initialBalance);
    await this.repository.save(account);

    // Publish events
    const events = account.getUncommittedEvents();
    await this.eventBus.publish(events);
  }

  private async handleDepositMoney(
    command: DepositMoneyCommand
  ): Promise<void> {
    const account = await this.repository.findById(command.accountId);
    if (!account) {
      throw new Error("Account not found");
    }

    account.deposit(command.amount);
    await this.repository.save(account);

    const events = account.getUncommittedEvents();
    await this.eventBus.publish(events);
  }
}

// Read models (optimized for queries)
interface AccountReadModel {
  accountId: string;
  balance: number;
  status: string;
  lastActivity: Date;
  transactionCount: number;
}

interface AccountSummaryReadModel {
  accountId: string;
  balance: number;
  status: string;
}

// Projections (build read models from events)
class AccountProjection {
  constructor(private db: ReadDatabase) {}

  async handleEvent(event: Event): Promise<void> {
    switch (event.eventType) {
      case "AccountOpened":
        await this.handleAccountOpened(event);
        break;
      case "MoneyDeposited":
        await this.handleMoneyDeposited(event);
        break;
      case "MoneyWithdrawn":
        await this.handleMoneyWithdrawn(event);
        break;
      case "AccountClosed":
        await this.handleAccountClosed(event);
        break;
    }
  }

  private async handleAccountOpened(event: Event): Promise<void> {
    await this.db.accounts.insert({
      accountId: event.aggregateId,
      balance: event.data.initialBalance,
      status: "Active",
      lastActivity: event.timestamp,
      transactionCount: 0
    });
  }

  private async handleMoneyDeposited(event: Event): Promise<void> {
    await this.db.accounts.update(
      { accountId: event.aggregateId },
      {
        $inc: { balance: event.data.amount, transactionCount: 1 },
        $set: { lastActivity: event.timestamp }
      }
    );
  }

  private async handleMoneyWithdrawn(event: Event): Promise<void> {
    await this.db.accounts.update(
      { accountId: event.aggregateId },
      {
        $inc: { balance: -event.data.amount, transactionCount: 1 },
        $set: { lastActivity: event.timestamp }
      }
    );
  }

  private async handleAccountClosed(event: Event): Promise<void> {
    await this.db.accounts.update(
      { accountId: event.aggregateId },
      {
        $set: {
          status: "Closed",
          lastActivity: event.timestamp
        }
      }
    );
  }
}

// Query service (read-only)
class AccountQueryService {
  constructor(private db: ReadDatabase) {}

  async getAccount(accountId: string): Promise<AccountReadModel | null> {
    return await this.db.accounts.findOne({ accountId });
  }

  async getAccountsByStatus(status: string): Promise<AccountSummaryReadModel[]> {
    return await this.db.accounts.find(
      { status },
      { projection: { accountId: 1, balance: 1, status: 1 } }
    );
  }

  async getHighBalanceAccounts(
    minBalance: number
  ): Promise<AccountSummaryReadModel[]> {
    return await this.db.accounts.find(
      { balance: { $gte: minBalance } },
      { projection: { accountId: 1, balance: 1, status: 1 } }
    );
  }
}

// Event bus for publishing events
class EventBus {
  private subscribers: Map<string, Function[]> = new Map();

  subscribe(eventType: string, handler: Function): void {
    if (!this.subscribers.has(eventType)) {
      this.subscribers.set(eventType, []);
    }
    this.subscribers.get(eventType)!.push(handler);
  }

  subscribeToAll(handler: Function): void {
    this.subscribe("*", handler);
  }

  async publish(events: Event[]): Promise<void> {
    for (const event of events) {
      // Call specific handlers
      const handlers = this.subscribers.get(event.eventType) || [];
      await Promise.all(handlers.map(h => h(event)));

      // Call wildcard handlers
      const allHandlers = this.subscribers.get("*") || [];
      await Promise.all(allHandlers.map(h => h(event)));
    }
  }
}

Saga 模式

使用由 Saga 协调的一系列本地事务,管理跨多个服务的分布式事务。

基于编排的 Saga

由中央编排器协调所有 Saga 参与者。

// Saga state
enum SagaStatus {
  Started = "Started",
  Completed = "Completed",
  Compensating = "Compensating",
  Compensated = "Compensated",
  Failed = "Failed"
}

interface SagaStep {
  name: string;
  action: () => Promise<void>;
  compensation: () => Promise<void>;
}

class OrderSaga {
  private sagaId: string;
  private status: SagaStatus;
  private completedSteps: string[] = [];
  private currentStep: number = 0;

  private steps: SagaStep[] = [
    {
      name: "CreateOrder",
      action: async () => await this.createOrder(),
      compensation: async () => await this.cancelOrder()
    },
    {
      name: "ReserveInventory",
      action: async () => await this.reserveInventory(),
      compensation: async () => await this.releaseInventory()
    },
    {
      name: "ProcessPayment",
      action: async () => await this.processPayment(),
      compensation: async () => await this.refundPayment()
    },
    {
      name: "ArrangeShipment",
      action: async () => await this.arrangeShipment(),
      compensation: async () => await this.cancelShipment()
    }
  ];

  constructor(
    private orderId: string,
    private customerId: string,
    private items: OrderItem[]
  ) {
    this.sagaId = generateId();
    this.status = SagaStatus.Started;
  }

  async execute(): Promise<void> {
    try {
      // Execute each step
      for (let i = 0; i < this.steps.length; i++) {
        this.currentStep = i;
        const step = this.steps[i];

        console.log(`Executing step: ${step.name}`);
        await step.action();
        this.completedSteps.push(step.name);
      }

      this.status = SagaStatus.Completed;
      console.log("Saga completed successfully");

    } catch (error) {
      console.error(`Saga failed at step ${this.currentStep}:`, error);
      await this.compensate();
    }
  }

  private async compensate(): Promise<void> {
    this.status = SagaStatus.Compensating;
    console.log("Starting compensation");

    // Compensate in reverse order
    for (let i = this.completedSteps.length - 1; i >= 0; i--) {
      const stepName = this.completedSteps[i];
      const step = this.steps.find(s => s.name === stepName);

      if (step) {
        try {
          console.log(`Compensating step: ${step.name}`);
          await step.compensation();
        } catch (error) {
          console.error(`Compensation failed for ${step.name}:`, error);
          // Log for manual intervention
        }
      }
    }

    this.status = SagaStatus.Compensated;
    console.log("Compensation completed");
  }

  // Step implementations
  private async createOrder(): Promise<void> {
    await orderService.create({
      orderId: this.orderId,
      customerId: this.customerId,
      items: this.items
    });
  }

  private async cancelOrder(): Promise<void> {
    await orderService.cancel(this.orderId);
  }

  private async reserveInventory(): Promise<void> {
    await inventoryService.reserve(this.orderId, this.items);
  }

  private async releaseInventory(): Promise<void> {
    await inventoryService.release(this.orderId);
  }

  private async processPayment(): Promise<void> {
    const total = this.calculateTotal();
    await paymentService.charge(this.customerId, total);
  }

  private async refundPayment(): Promise<void> {
    const total = this.calculateTotal();
    await paymentService.refund(this.customerId, total);
  }

  private async arrangeShipment(): Promise<void> {
    await shippingService.createShipment(this.orderId);
  }

  private async cancelShipment(): Promise<void> {
    await shippingService.cancelShipment(this.orderId);
  }

  private calculateTotal(): Money {
    return this.items.reduce(
      (sum, item) => sum.add(item.price.multiply(item.quantity)),
      new Money(0, "USD")
    );
  }
}

// Orchestrator service
class SagaOrchestrator {
  private activeSagas: Map<string, OrderSaga> = new Map();

  async startOrderSaga(
    orderId: string,
    customerId: string,
    items: OrderItem[]
  ): Promise<void> {
    const saga = new OrderSaga(orderId, customerId, items);
    this.activeSagas.set(saga.sagaId, saga);

    try {
      await saga.execute();
    } finally {
      this.activeSagas.delete(saga.sagaId);
    }
  }

  getSagaStatus(sagaId: string): SagaStatus | null {
    const saga = this.activeSagas.get(sagaId);
    return saga ? saga.status : null;
  }
}
基于协同的 Saga

服务通过事件进行协调,无需中央编排器。

// Event-driven saga with choreography
class OrderCreatedEvent {
  constructor(
    public orderId: string,
    public customerId: string,
    public items: OrderItem[]
  ) {}
}

class InventoryReservedEvent {
  constructor(
    public orderId: string,
    public reservationId: string
  ) {}
}

class PaymentProcessedEvent {
  constructor(
    public orderId: string,
    public paymentId: string
  ) {}
}

class ShipmentArrangedEvent {
  constructor(
    public orderId: string,
    public shipmentId: string
  ) {}
}

// Compensation events
class InventoryReservationFailedEvent {
  constructor(
    public orderId: string,
    public reason: string
  ) {}
}

class PaymentFailedEvent {
  constructor(
    public orderId: string,
    public reason: string
  ) {}
}

// Order service
class OrderService {
  constructor(private eventBus: EventBus) {
    // Subscribe to compensation events
    eventBus.subscribe("InventoryReservationFailed",
      this.handleInventoryReservationFailed.bind(this));
    eventBus.subscribe("PaymentFailed",
      this.handlePaymentFailed.bind(this));
  }

  async createOrder(order: CreateOrderRequest): Promise<void> {
    // Create order in pending state
    await this.repository.save({
      ...order,
      status: "Pending"
    });

    // Publish event to trigger next step
    await this.eventBus.publish(
      new OrderCreatedEvent(order.orderId, order.customerId, order.items)
    );
  }

  private async handleInventoryReservationFailed(
    event: InventoryReservationFailedEvent
  ): Promise<void> {
    await this.repository.updateStatus(event.orderId, "Cancelled");
    console.log(`Order ${event.orderId} cancelled: ${event.reason}`);
  }

  private async handlePaymentFailed(event: PaymentFailedEvent): Promise<void> {
    await this.repository.updateStatus(event.orderId, "PaymentFailed");
    // Trigger inventory release
    await this.eventBus.publish(
      new ReleaseInventoryCommand(event.orderId)
    );
  }
}

// Inventory service
class InventoryService {
  constructor(private eventBus: EventBus) {
    eventBus.subscribe("OrderCreated",
      this.handleOrderCreated.bind(this));
    eventBus.subscribe("ReleaseInventory",
      this.handleReleaseInventory.bind(this));
  }

  private async handleOrderCreated(event: OrderCreatedEvent): Promise<void> {
    try {
      // Reserve inventory
      const reservationId = await this.reserveItems(event.items);

      // Publish success event
      await this.eventBus.publish(
        new InventoryReservedEvent(event.orderId, reservationId)
      );
    } catch (error) {
      // Publish failure event
      await this.eventBus.publish(
        new InventoryReservationFailedEvent(
          event.orderId,
          error.message
        )
      );
    }
  }

  private async handleReleaseInventory(
    command: ReleaseInventoryCommand
  ): Promise<void> {
    await this.releaseReservation(command.orderId);
  }
}

// Payment service
class PaymentService {
  constructor(private eventBus: EventBus) {
    eventBus.subscribe("InventoryReserved",
      this.handleInventoryReserved.bind(this));
    eventBus.subscribe("RefundPayment",
      this.handleRefundPayment.bind(this));
  }

  private async handleInventoryReserved(
    event: InventoryReservedEvent
  ): Promise<void> {
    try {
      // Process payment
      const paymentId = await this.chargeCustomer(event.orderId);

      // Publish success event
      await this.eventBus.publish(
        new PaymentProcessedEvent(event.orderId, paymentId)
      );
    } catch (error) {
      // Publish failure event
      await this.eventBus.publish(
        new PaymentFailedEvent(event.orderId, error.message)
      );
    }
  }

  private async handleRefundPayment(
    command: RefundPaymentCommand
  ): Promise<void> {
    await this.refund(command.orderId);
  }
}

API 网关模式

为客户端提供单一入口,将请求路由到适当的微服务,并处理横切关注点。

实现
class APIGateway {
  constructor(
    private router: Router,
    private authService: AuthService,
    private rateLimiter: RateLimiter,
    private circuitBreaker: CircuitBreaker,
    private loadBalancer: LoadBalancer
  ) {
    this.setupRoutes();
  }

  private setupRoutes(): void {
    // User service routes
    this.router.get("/api/users/:id",
      this.authenticate.bind(this),
      this.rateLimit.bind(this),
      this.getUserHandler.bind(this)
    );

    // Order service routes
    this.router.post("/api/orders",
      this.authenticate.bind(this),
      this.rateLimit.bind(this),
      this.createOrderHandler.bind(this)
    );

    // Product service routes
    this.router.get("/api/products",
      this.rateLimit.bind(this),
      this.getProductsHandler.bind(this)
    );
  }

  // Middleware: Authentication
  private async authenticate(
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    try {
      const token = req.headers.authorization?.replace("Bearer ", "");
      if (!token) {
        res.status(401).json({ error: "Unauthorized" });
        return;
      }

      const user = await this.authService.validateToken(token);
      req.user = user;
      next();
    } catch (error) {
      res.status(401).json({ error: "Invalid token" });
    }
  }

  // Middleware: Rate limiting
  private async rateLimit(
    req: Request,
    res: Response,
    next: NextFunction
  ): Promise<void> {
    const clientId = req.ip || req.user?.id;

    if (await this.rateLimiter.isAllowed(clientId)) {
      next();
    } else {
      res.status(429).json({ error: "Too many requests" });
    }
  }

  // Handler: Get user
  private async getUserHandler(req: Request, res: Response): Promise<void> {
    try {
      const userId = req.params.id;

      // Call user service with circuit breaker
      const user = await this.circuitBreaker.execute(
        "user-service",
        async () => {
          const instance = this.loadBalancer.getInstance("user-service");
          return await instance.getUser(userId);
        }
      );

      res.json(user);
    } catch (error) {
      res.status(500).json({ error: "Internal server error" });
    }
  }

  // Handler: Create order
  private async createOrderHandler(
    req: Request,
    res: Response
  ): Promise<void> {
    try {
      // Aggregate data from multiple services
      const [user, products, inventory] = await Promise.all([
        this.callUserService(req.user.id),
        this.callProductService(req.body.items),
        this.callInventoryService(req.body.items)
      ]);

      // Call order service
      const order = await this.callOrderService({
        user,
        items: req.body.items,
        inventory
      });

      res.status(201).json(order);
    } catch (error) {
      res.status(500).json({ error: "Internal server error" });
    }
  }

  private async callUserService(userId: string): Promise<User> {
    return await this.circuitBreaker.execute("user-service", async () => {
      const instance = this.loadBalancer.getInstance("user-service");
      return await instance.getUser(userId);
    });
  }

  private async callProductService(items: any[]): Promise<Product[]> {
    return await this.circuitBreaker.execute("product-service", async () => {
      const instance = this.loadBalancer.getInstance("product-service");
      return await instance.getProducts(items.map(i => i.productId));
    });
  }
}

// Rate limiter implementation
class RateLimiter {
  private requests: Map<string, number[]> = new Map();

  constructor(
    private maxRequests: number = 100,
    private windowMs: number = 60000 // 1 minute
  ) {}

  async isAllowed(clientId: string): Promise<boolean> {
    const now = Date.now();
    const windowStart = now - this.windowMs;

    // Get existing requests
    const clientRequests = this.requests.get(clientId) || [];

    // Filter out old requests
    const recentRequests = clientRequests.filter(t => t > windowStart);

    // Check if under limit
    if (recentRequests.length < this.maxRequests) {
      recentRequests.push(now);
      this.requests.set(clientId, recentRequests);
      return true;
    }

    return false;
  }
}

// Load balancer
class LoadBalancer {
  private services: Map<string, ServiceInstance[]> = new Map();
  private currentIndex: Map<string, number> = new Map();

  registerService(name: string, instance: ServiceInstance): void {
    if (!this.services.has(name)) {
      this.services.set(name, []);
      this.currentIndex.set(name, 0);
    }
    this.services.get(name)!.push(instance);
  }

  getInstance(serviceName: string): ServiceInstance {
    const instances = this.services.get(serviceName);
    if (!instances || instances.length === 0) {
      throw new Error(`No instances available for ${serviceName}`);
    }

    // Round-robin selection
    const index = this.currentIndex.get(serviceName)!;
    const instance = instances[index];

    // Update index for next call
    this.currentIndex.set(
      serviceName,
      (index + 1) % instances.length
    );

    return instance;
  }
}
前端后端(BFF)模式
// Separate BFFs for different clients
class WebBFF {
  constructor(
    private userService: UserService,
    private productService: ProductService,
    private orderService: OrderService
  ) {}

  // Optimized for web client needs
  async getHomePage(userId: string): Promise<WebHomePageData> {
    const [user, recommendations, recentOrders] = await Promise.all([
      this.userService.getUser(userId),
      this.productService.getRecommendations(userId, 10),
      this.orderService.getRecentOrders(userId, 5)
    ]);

    return {
      user: {
        name: user.name,
        email: user.email,
        avatar: user.avatarUrl
      },
      recommendations: recommendations.map(p => ({
        id: p.id,
        name: p.name,
        price: p.price,
        imageUrl: p.images[0], // Full images for web
        rating: p.averageRating
      })),
      recentOrders: recentOrders.map(o => ({
        orderId: o.id,
        date: o.createdAt,
        total: o.totalAmount,
        status: o.status,
        itemCount: o.items.length
      }))
    };
  }
}

class MobileBFF {
  constructor(
    private userService: UserService,
    private productService: ProductService,
    private orderService: OrderService
  ) {}

  // Optimized for mobile client needs
  async getHomePage(userId: string): Promise<MobileHomePageData> {
    const [user, recommendations, recentOrders] = await Promise.all([
      this.userService.getUser(userId),
      this.productService.getRecommendations(userId, 5), // Fewer items
      this.orderService.getRecentOrders(userId, 3)
    ]);

    return {
      user: {
        name: user.name,
        avatar: user.avatarThumbnailUrl // Smaller images for mobile
      },
      recommendations: recommendations.map(p => ({
        id: p.id,
        name: p.name,
        price: p.price,
        thumbnail: p.thumbnails.small, // Optimized image size
        rating: Math.round(p.averageRating) // Simplified rating
      })),
      recentOrders: recentOrders.map(o => ({
        id: o.id,
        date: o.createdAt.toISOString(),
        total: o.totalAmount,
        status: o.status
      }))
    };
  }
}

服务网格模式

用于服务间通信的基础设施层,提供可观测性、流量管理和安全保障。

主要特性
// Service mesh configuration example (Istio)
const serviceMeshConfig = {
  // Traffic management
  virtualService: {
    name: "product-service",
    hosts: ["product-service"],
    http: [
      {
        match: [{ uri: { prefix: "/api/v1" } }],
        route: [
          {
            destination: {
              host: "product-service",
              subset: "v1"
            },
            weight: 90
          },
          {
            destination: {
              host: "product-service",
              subset: "v2"
            },
            weight: 10 // Canary deployment
          }
        ],
        retries: {
          attempts: 3,
          perTryTimeout: "2s"
        },
        timeout: "10s"
      }
    ]
  },

  // Destination rules
  destinationRule: {
    name: "product-service",
    host: "product-service",
    trafficPolicy: {
      connectionPool: {
        tcp: {
          maxConnections: 100
        },
        http: {
          http1MaxPendingRequests: 50,
          http2MaxRequests: 100,
          maxRequestsPerConnection: 2
        }
      },
      loadBalancer: {
        simple: "ROUND_ROBIN"
      },
      outlierDetection: {
        consecutive5xxErrors: 5,
        interval: "30s",
        baseEjectionTime: "30s",
        maxEjectionPercent: 50
      }
    },
    subsets: [
      {
        name: "v1",
        labels: { version: "v1" }
      },
      {
        name: "v2",
        labels: { version: "v2" }
      }
    ]
  },

  // Circuit breaker
  circuitBreaker: {
    consecutiveErrors: 5,
    interval: "30s",
    baseEjectionTime: "30s",
    maxEjectionPercent: 50
  }
};

弹性模式

断路器

停止向故障服务发送请求,防止故障级联。

enum CircuitState {
  Closed = "Closed",     // Normal operation
  Open = "Open",         // Blocking requests
  HalfOpen = "HalfOpen"  // Testing if service recovered
}

class CircuitBreaker {
  private state: CircuitState = CircuitState.Closed;
  private failureCount: number = 0;
  private successCount: number = 0;
  private lastFailureTime: number = 0;

  constructor(
    private failureThreshold: number = 5,
    private successThreshold: number = 2,
    private timeout: number = 60000 // 1 minute
  ) {}

  async execute<T>(operation: () => Promise<T>): Promise<T> {
    if (this.state === CircuitState.Open) {
      if (Date.now() - this.lastFailureTime > this.timeout) {
        this.state = CircuitState.HalfOpen;
        this.successCount = 0;
      } else {
        throw new Error("Circuit breaker is OPEN");
      }
    }

    try {
      const result = await operation();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  private onSuccess(): void {
    this.failureCount = 0;

    if (this.state === CircuitState.HalfOpen) {
      this.successCount++;
      if (this.successCount >= this.successThreshold) {
        this.state = CircuitState.Closed;
        this.successCount = 0;
      }
    }
  }

  private onFailure(): void {
    this.failureCount++;
    this.lastFailureTime = Date.now();

    if (this.failureCount >= this.failureThreshold) {
      this.state = CircuitState.Open;
    }
  }

  getState(): CircuitState {
    return this.state;
  }
}
重试模式

使用指数退避自动重试失败的操作。

class RetryPolicy {
  constructor(
    private maxRetries: number = 3,
    private initialDelayMs: number = 100,
    private maxDelayMs: number = 5000,
    private backoffMultiplier: number = 2
  ) {}

  async execute<T>(
    operation: () => Promise<T>,
    isRetryable: (error: Error) => boolean = () => true
  ): Promise<T> {
    let lastError: Error;

    for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
      try {
        return await operation();
      } catch (error) {
        lastError = error as Error;

        if (attempt === this.maxRetries || !isRetryable(lastError)) {
          throw lastError;
        }

        const delay = this.calculateDelay(attempt);
        await this.sleep(delay);
      }
    }

    throw lastError!;
  }

  private calculateDelay(attempt: number): number {
    const delay = this.initialDelayMs * Math.pow(this.backoffMultiplier, attempt);
    return Math.min(delay, this.maxDelayMs);
  }

  private sleep(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

// Usage
const retryPolicy = new RetryPolicy(3, 100, 5000, 2);

await retryPolicy.execute(
  async () => await apiClient.get("/users/123"),
  (error) => error.statusCode >= 500 // Only retry server errors
);
舱壁模式

隔离资源,防止故障影响整个系统。

class Bulkhead {
  private activeRequests: number = 0;
  private queue: Array<{
    resolve: (value: any) => void;
    reject: (error: any) => void;
    operation: () => Promise<any>;
  }> = [];

  constructor(
    private maxConcurrent: number = 10,
    private maxQueueSize: number = 100
  ) {}

  async execute<T>(operation: () => Promise<T>): Promise<T> {
    if (this.activeRequests < this.maxConcurrent) {
      return await this.executeOperation(operation);
    }

    if (this.queue.length >= this.maxQueueSize) {
      throw new Error("Bulkhead queue full");
    }

    return new Promise((resolve, reject) => {
      this.queue.push({ resolve, reject, operation });
    });
  }

  private async executeOperation<T>(
    operation: () => Promise<T>
  ): Promise<T> {
    this.activeRequests++;

    try {
      const result = await operation();
      this.processQueue();
      return result;
    } catch (error) {
      this.processQueue();
      throw error;
    } finally {
      this.activeRequests--;
    }
  }

  private processQueue(): void {
    if (this.queue.length > 0 &&
        this.activeRequests < this.maxConcurrent) {
      const { resolve, reject, operation } = this.queue.shift()!;

      this.executeOperation(operation)
        .then(resolve)
        .catch(reject);
    }
  }
}
超时模式

设置时间限制,避免无限期等待。

class TimeoutPolicy {
  constructor(private timeoutMs: number = 30000) {}

  async execute<T>(operation: () => Promise<T>): Promise<T> {
    return Promise.race([
      operation(),
      this.timeout()
    ]);
  }

  private timeout(): Promise<never> {
    return new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error(`Operation timed out after ${this.timeoutMs}ms`));
      }, this.timeoutMs);
    });
  }
}
回退模式

操作失败时提供替代响应。

class FallbackPolicy<T> {
  constructor(private fallbackFn: () => Promise<T>) {}

  async execute(operation: () => Promise<T>): Promise<T> {
    try {
      return await operation();
    } catch (error) {
      console.warn("Operation failed, using fallback:", error);
      return await this.fallbackFn();
    }
  }
}

// Usage
const getUserWithFallback = new FallbackPolicy(async () => ({
  id: "default",
  name: "Guest User",
  email: "[email protected]"
}));

const user = await getUserWithFallback.execute(
  async () => await userService.getUser(userId)
);
组合弹性策略
class ResilientClient {
  private circuitBreaker: CircuitBreaker;
  private retryPolicy: RetryPolicy;
  private timeoutPolicy: TimeoutPolicy;
  private fallbackPolicy: FallbackPolicy<any>;
  private bulkhead: Bulkhead;

  constructor() {
    this.circuitBreaker = new CircuitBreaker(5, 2, 60000);
    this.retryPolicy = new RetryPolicy(3, 100, 5000, 2);
    this.timeoutPolicy = new TimeoutPolicy(10000);
    this.fallbackPolicy = new FallbackPolicy(async () => null);
    this.bulkhead = new Bulkhead(10, 100);
  }

  async call<T>(
    operation: () => Promise<T>,
    options?: {
      timeout?: number;
      retries?: number;
      fallback?: () => Promise<T>;
    }
  ): Promise<T> {
    const timeoutPolicy = options?.timeout
      ? new TimeoutPolicy(options.timeout)
      : this.timeoutPolicy;

    const fallbackPolicy = options?.fallback
      ? new FallbackPolicy(options.fallback)
      : this.fallbackPolicy;

    return await fallbackPolicy.execute(async () => {
      return await this.bulkhead.execute(async () => {
        return await this.circuitBreaker.execute(async () => {
          return await this.retryPolicy.execute(async () => {
            return await timeoutPolicy.execute(operation);
          });
        });
      });
    });
  }
}

可扩展性模式

水平扩展(横向扩展)

增加更多实例以处理增长的负载。

// Load balancer for horizontal scaling
class RoundRobinLoadBalancer {
  private instances: string[] = [];
  private currentIndex: number = 0;

  addInstance(url: string): void {
    this.instances.push(url);
  }

  removeInstance(url: string): void {
    this.instances = this.instances.filter(i => i !== url);
  }

  getNextInstance(): string {
    if (this.instances.length === 0) {
      throw new Error("No instances available");
    }

    const instance = this.instances[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.instances.length;
    return instance;
  }
}

// Auto-scaling based on metrics
class AutoScaler {
  constructor(
    private minInstances: number = 2,
    private maxInstances: number = 10,
    private targetCPU: number = 70
  ) {}

  async scale(currentInstances: number, currentCPU: number): Promise<number> {
    if (currentCPU > this.targetCPU) {
      // Scale up
      const desiredInstances = Math.ceil(
        currentInstances * (currentCPU / this.targetCPU)
      );
      return Math.min(desiredInstances, this.maxInstances);
    } else if (currentCPU < this.targetCPU * 0.5) {
      // Scale down
      const desiredInstances = Math.floor(
        currentInstances * (currentCPU / this.targetCPU)
      );
      return Math.max(desiredInstances, this.minInstances);
    }

    return currentInstances;
  }
}
缓存策略
// Cache-aside pattern
class CacheAsideRepository {
  constructor(
    private cache: Cache,
    private database: Database,
    private ttl: number = 3600
  ) {}

  async get(id: string): Promise<any> {
    // Try cache first
    const cached = await this.cache.get(id);
    if (cached) {
      return cached;
    }

    // Cache miss - get from database
    const data = await this.database.findById(id);
    if (data) {
      await this.cache.set(id, data, this.ttl);
    }

    return data;
  }

  async update(id: string, data: any): Promise<void> {
    // Update database
    await this.database.update(id, data);

    // Invalidate cache
    await this.cache.delete(id);
  }
}

// Write-through cache
class WriteThroughCache {
  constructor(
    private cache: Cache,
    private database: Database
  ) {}

  async write(id: string, data: any): Promise<void> {
    // Write to both cache and database
    await Promise.all([
      this.cache.set(id, data),
      this.database.save(id, data)
    ]);
  }
}

// Write-behind cache
class WriteBehindCache {
  private writeQueue: Map<string, any> = new Map();

  constructor(
    private cache: Cache,
    private database: Database,
    private flushInterval: number = 5000
  ) {
    this.startFlushInterval();
  }

  async write(id: string, data: any): Promise<void> {
    // Write to cache immediately
    await this.cache.set(id, data);

    // Queue for database write
    this.writeQueue.set(id, data);
  }

  private startFlushInterval(): void {
    setInterval(async () => {
      await this.flush();
    }, this.flushInterval);
  }

  private async flush(): Promise<void> {
    const entries = Array.from(this.writeQueue.entries());
    this.writeQueue.clear();

    await Promise.all(
      entries.map(([id, data]) => this.database.save(id, data))
    );
  }
}
数据库分片
// Shard key-based routing
class ShardRouter {
  private shards: Map<number, Database> = new Map();
  private totalShards: number;

  constructor(shards: Database[]) {
    this.totalShards = shards.length;
    shards.forEach((shard, index) => {
      this.shards.set(index, shard);
    });
  }

  private getShardIndex(key: string): number {
    // Hash-based sharding
    const hash = this.hashCode(key);
    return Math.abs(hash) % this.totalShards;
  }

  private hashCode(str: string): number {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // Convert to 32-bit integer
    }
    return hash;
  }

  getShard(key: string): Database {
    const index = this.getShardIndex(key);
    return this.shards.get(index)!;
  }

  async save(key: string, data: any): Promise<void> {
    const shard = this.getShard(key);
    await shard.save(key, data);
  }

  async find(key: string): Promise<any> {
    const shard = this.getShard(key);
    return await shard.findById(key);
  }
}

最佳实践

架构设计
  1. 从领域入手:在选择模式前了解业务需求
  2. 保持简单:不要过度设计;只在需要时增加复杂性
  3. 面向故障进行设计:假设服务会发生故障;构建弹性能力
  4. 松耦合:服务应彼此独立,并可单独部署
  5. 高内聚:将相关功能组合在一起
  6. API 优先设计:在实现前定义契约
  7. 版本策略:从一开始就规划 API 的演进
  8. 可观测性:从第一天起就构建日志、指标和追踪能力
领域驱动设计
  1. 与领域专家协作:建立共同理解
  2. 使用通用语言:确保术语在各处保持一致
  3. 建模限界上下文:清晰的边界可避免模型混淆
  4. 小型聚合:性能更佳,边界更清晰
  5. 通过 ID 引用:聚合通过标识引用其他聚合
  6. 保护不变量:聚合根负责强制执行所有业务规则
  7. 领域事件:记录重要的业务事件
  8. 每个聚合一个仓储:每个聚合根对应一个仓储
事件溯源与 CQRS
  1. 事件命名:使用过去时且具有明确业务含义的名称
  2. 事件不可变性:绝不修改已发布的事件
  3. 事件版本管理:为事件架构的演进做好规划
  4. 快照:用于较长的事件流
  5. 幂等处理器:事件可能会被处理多次
  6. 关注点分离:读写使用不同的模型
  7. 最终一致性:接受延迟并清楚说明
  8. 监控:跟踪投影延迟和事件处理情况
微服务
  1. 服务规模:规模要小到易于理解,又要大到足以提供价值
  2. 数据所有权:每个服务拥有自己的数据
  3. 异步通信:优先使用事件,而非同步调用
  4. 服务发现:动态定位服务
  5. 配置管理:集中管理特定于环境的配置
  6. 独立部署:各服务无需协调即可部署
  7. 故障隔离:使用断路器和舱壁隔离
  8. 分布式追踪:在服务调用间传递关联 ID
性能与可扩展性
  1. 先测量:优化前先进行性能分析
  2. 策略性缓存:选择合适的层、数据和 TTL
  3. 异步处理:将耗时操作移至后台
  4. 连接池:重用数据库/HTTP 连接
  5. 分页:绝不返回无界结果集
  6. 压缩:减少网络传输量
  7. 使用 CDN:从边缘节点提供静态资源
  8. 数据库索引:针对查询模式创建索引,而非为所有列创建索引
安全
  1. 纵深防御:采用多层安全措施
  2. 最小权限:仅授予必要的最少权限
  3. 传输加密:所有网络通信均使用 TLS
  4. 静态数据加密:对存储中的敏感数据进行加密
  5. 输入验证:验证并清理所有输入
  6. 身份验证:验证身份(JWT、OAuth)
  7. 授权:验证权限(RBAC、ABAC)
  8. 审计日志:跟踪与安全相关的事件
测试
  1. 测试金字塔:大量单元测试、较少集成测试和少量端到端测试
  2. 测试行为:关注业务逻辑,而非实现方式
  3. 契约测试:验证服务之间的 API 契约
  4. 混沌工程:测试故障场景
  5. 性能测试:上线前进行负载测试
  6. 安全测试:自动扫描漏洞
  7. 冒烟测试:部署后快速验证
  8. 金丝雀部署:逐步发布以发现问题
监控与可观测性
  1. 结构化日志:包含上下文信息的 JSON 日志
  2. 指标收集:RED 指标(速率、错误、持续时间)
  3. 分布式追踪:追踪请求在各服务间的流转
  4. 健康检查:提供存活和就绪端点
  5. 告警:针对症状而非原因发出告警
  6. 仪表盘:一目了然地查看关键指标
  7. SLO/SLA:定义并跟踪服务级别
  8. 事件响应:为常见问题编写操作手册

资源

书籍
  • Eric Evans 著《领域驱动设计》
  • Vaughn Vernon 著《实现领域驱动设计》
  • Chris Richardson 著《微服务模式》
  • Sam Newman 著《构建微服务》
  • Martin Kleppmann 著《设计数据密集型应用》
在线资源

技能版本:1.0.0 最后更新:2025 年 10 月 技能类别:企业架构、系统设计、分布式系统

评论

支持 Markdown