Skip to content

边缘计算与 Serverless 最佳实践

在 Cloudflare Workers、Vercel Edge Functions 等 Serverless 边缘环境中,CPU 执行时间通常受到极其严苛的物理限制(例如 Cloudflare Workers 免费计划仅有 10ms ~ 50ms CPU Time 限制)。

传统的 IoC 框架由于每次请求都需要反编译类、查元数据表与动态解析依赖树,极易耗尽边缘 CPU 时间导致超时报错。


核心架构:“静态图单例 + 请求级容器多例”

Path-IoC 针对 Serverless 边缘架构确立了两阶段彻底解耦机制:

mermaid
sequenceDiagram
    participant Worker as Worker 进程冷启动 (Cold Start)
    participant Request as HTTP 请求到来 (Request Arrival)
    participant Engine as @path-ioc/core

    Worker->>Engine: 1. compileModuleGraph(modules)
    Note over Engine: 执行 1 次 Kahn 拓扑排序与校验 (约 1.7ms)<br>生成静态 CompiledGraph 全局缓存
    
    Request->>Engine: 2. instantiateModuleContainer(compiledGraph, reqContainer)
    Note over Engine: 直通装配当前请求容器 (耗时仅 21.2 µs)<br>挂载 c.varContext 请求上下文
    Engine-->>Request: 返回隔离后的请求容器 (零重复拓扑损耗)

在 Hono / Cloudflare Workers 中的实战代码

1. 中间件隔离当前请求上下文

typescript
import { Hono, Context } from "hono";
import { createModularContainer } from "virtual:modular-container";

type AppEnv = {
  Variables: {
    modularContainer: ModularContainer;
  };
};

const app = new Hono<AppEnv>();

// 在 HTTP 中间件中挂载请求级隔离容器
app.use("*", async (c, next) => {
  const reqContainer = {
    varContext: c, // 注入当前请求的 Context (包含 Headers, Auth, Env 等)
  } as any;

  // 内部自动复用启动期预编译的 DAG 静态图,填充仅耗时 21.2 微秒!
  await createModularContainer(reqContainer);

  c.set("modularContainer", reqContainer);
  await next();
});

// 业务路由直接消费容器
app.get("/api/orders", async (c) => {
  const { orderService } = c.get("modularContainer");
  const data = await orderService.listMyOrders();
  return c.json({ result: true, data });
});

export default app;

重型资源复用:进程级单例高阶函数 (memoizeModule)

在多请求隔离模式下,数据库连接池(Connection Pool)或 Redis 客户端无需每次请求都重复创建。可以使用高阶函数闭包实现跨请求的全局单例复用:

typescript
// 辅助函数:进程级单例闭包
export const memoizeModule = <T extends (...args: any[]) => any>(fn: T): T => {
  let cache: any;
  let initialized = false;
  return ((...args: any[]) => {
    if (!initialized) {
      cache = fn(...args);
      initialized = true;
    }
    return cache;
  }) as T;
};

// src/modules/infra/db-pool/index.ts
export const main = memoizeModule((container: ModularContainer) => {
  const { varContext } = container;
  // 仅在首次请求时创建连接池,后续所有 HTTP 请求直接共享同一连接实例!
  const pool = createDbPool(varContext.env.DATABASE_URL);
  return pool;
});

Released under the MIT License.