后端配置指南

AppSolve 后端服务配置指南

后端配置指南

本指南提供 AppSolve 后端服务的详细配置说明,包括环境变量、Firebase Admin、Cloudflare 资源、AI 服务集成等配置。

环境变量配置

1. 核心配置

创建 .dev.vars 文件用于本地开发:

# 环境标识
ENVIRONMENT=development

# Firebase Admin SDK
FIREBASE_PROJECT_ID=your-project-id
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-xxx@your-project.iam.gserviceaccount.com

# API 密钥(用于服务间通信)
API_SECRET_KEY=your-secure-api-secret-key

# CORS 配置
ALLOWED_ORIGINS=http://localhost:3000,https://yourdomain.com

2. AI 服务配置

2.1 OpenAI 配置

# OpenAI API
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4-turbo-preview
OPENAI_MAX_TOKENS=2000
OPENAI_TEMPERATURE=0.7

2.2 Google AI (Gemini) 配置

# Google AI
GOOGLE_AI_API_KEY=AIza...
GEMINI_MODEL=gemini-pro
GEMINI_MAX_OUTPUT_TOKENS=2048

2.3 图像生成服务 (FAL.ai)

# FAL.ai
FAL_KEY=your-fal-api-key
FAL_MODEL_IMAGE=fal-ai/flux/schnell
FAL_MODEL_VIDEO=fal-ai/kling-video/v1/standard/text-to-video

3. 第三方服务配置

# Sentry 错误监控
SENTRY_DSN=https://xxx@xxx.ingest.sentry.io/xxx

# 速率限制
RATE_LIMIT_REQUESTS=100
RATE_LIMIT_WINDOW_MS=60000

# 缓存配置
CACHE_TTL_SECONDS=3600
CACHE_MAX_AGE=86400

Cloudflare 配置

1. Workers 配置

1.1 wrangler.jsonc 详解

{
  "name": "appsolve-backend",
  "main": "src/index.ts",
  "compatibility_date": "2024-01-01",

  // KV 命名空间绑定
  "kv_namespaces": [
    {
      "binding": "CACHE",
      "id": "your-cache-namespace-id",
      "preview_id": "your-cache-preview-id"
    },
    {
      "binding": "ANALYTICS",
      "id": "your-analytics-namespace-id",
      "preview_id": "your-analytics-preview-id"
    },
    {
      "binding": "QUOTA",
      "id": "your-quota-namespace-id",
      "preview_id": "your-quota-preview-id"
    }
  ],

  // R2 存储桶绑定
  "r2_buckets": [
    {
      "binding": "R2_MEDIA_STORAGE",
      "bucket_name": "media-storage"
    }
  ],

  // 环境变量
  "vars": {
    "ENVIRONMENT": "production",
    "LOG_LEVEL": "info"
  }
}

1.2 创建 KV 命名空间

# 缓存存储
pnpm wrangler kv:namespace create "CACHE"
pnpm wrangler kv:namespace create "CACHE" --preview

# 分析数据存储
pnpm wrangler kv:namespace create "ANALYTICS"
pnpm wrangler kv:namespace create "ANALYTICS" --preview

# 配额管理存储
pnpm wrangler kv:namespace create "QUOTA"
pnpm wrangler kv:namespace create "QUOTA" --preview

2. R2 存储配置

2.1 创建存储桶

# 媒体文件存储
pnpm wrangler r2 bucket create media-storage

# 配置 CORS(如需要)
pnpm wrangler r2 bucket cors put media-storage --file cors-config.json

2.2 CORS 配置示例

// cors-config.json
[
  {
    "AllowedOrigins": ["https://yourdomain.com"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]

2.3 存储结构

media-storage/
├── images/
│   ├── generated/     # AI 生成的图像
│   ├── uploads/       # 用户上传
│   └── thumbnails/    # 缩略图
├── videos/
│   ├── generated/     # AI 生成的视频
│   └── processed/     # 处理后的视频
└── temp/             # 临时文件

3. Workers 限制与优化

3.1 资源限制

  • CPU 时间:10ms (免费) / 50ms (付费)
  • 内存:128MB
  • 脚本大小:1MB (压缩后)
  • 请求大小:100MB

3.2 优化策略

// 使用 Durable Objects 处理长任务
export class VideoProcessor {
  state: DurableObjectState;

  constructor(state: DurableObjectState) {
    this.state = state;
  }

  async fetch(request: Request) {
    // 处理视频生成任务
  }
}

Firebase Admin 配置

1. 服务账号设置

1.1 生成服务账号

  1. Firebase Console > 项目设置 > 服务账号
  2. 生成新的私钥
  3. 安全存储 JSON 文件

1.2 配置权限

确保服务账号具有以下角色:

  • Firebase Admin SDK Administrator
  • Cloud Datastore User
  • Storage Admin

2. Firestore 配置

2.1 数据模型

// 用户集合
interface UserDocument {
  uid: string;
  email: string;
  displayName?: string;
  photoURL?: string;
  tier: "free" | "pro" | "premium";
  credits: number;
  createdAt: Timestamp;
  updatedAt: Timestamp;
}

// 任务集合
interface TaskDocument {
  userId: string;
  type: "image" | "video";
  status: "pending" | "processing" | "completed" | "failed";
  input: any;
  output?: any;
  error?: string;
  createdAt: Timestamp;
  completedAt?: Timestamp;
}

2.2 索引优化

// firestore.indexes.json
{
  "indexes": [
    {
      "collectionGroup": "imageTasks",
      "queryScope": "COLLECTION",
      "fields": [
        { "fieldPath": "userId", "order": "ASCENDING" },
        { "fieldPath": "status", "order": "ASCENDING" },
        { "fieldPath": "createdAt", "order": "DESCENDING" }
      ]
    }
  ]
}

AI 服务集成

1. 提示词管理

// src/infrastructure/ai/prompts.ts
export const IMAGE_GENERATION_PROMPTS = {
  enhance: (input: string) => `
    Enhance the following image description for AI generation:
    Original: ${input}
    
    Add artistic details, lighting, composition, and style.
    Keep it concise but descriptive.
  `,

  style: (input: string, style: string) => `
    Apply ${style} style to: ${input}
  `,
};

2. 模型选择策略

// src/infrastructure/ai/model-selector.ts
export class ModelSelector {
  selectImageModel(requirements: ImageRequirements): string {
    if (requirements.quality === "premium") {
      return "fal-ai/flux/dev";
    }
    if (requirements.speed === "fast") {
      return "fal-ai/flux/schnell";
    }
    return "fal-ai/stable-diffusion-xl";
  }
}

3. 错误处理与重试

// src/infrastructure/ai/retry-handler.ts
export class AIRetryHandler {
  async executeWithRetry<T>(
    fn: () => Promise<T>,
    options = { maxRetries: 3, backoff: 1000 }
  ): Promise<T> {
    for (let i = 0; i <= options.maxRetries; i++) {
      try {
        return await fn();
      } catch (error) {
        if (i === options.maxRetries) throw error;

        await new Promise((resolve) =>
          setTimeout(resolve, options.backoff * Math.pow(2, i))
        );
      }
    }
    throw new Error("Max retries exceeded");
  }
}

缓存策略

1. 多层缓存架构

// src/infrastructure/cache/cache-strategy.ts
export class CacheStrategy {
  constructor(
    private memory: MemoryCache,
    private kv: KVCache,
    private cdn: CDNCache
  ) {}

  async get(key: string): Promise<any> {
    // L1: 内存缓存
    let value = this.memory.get(key);
    if (value) return value;

    // L2: KV 缓存
    value = await this.kv.get(key);
    if (value) {
      this.memory.set(key, value);
      return value;
    }

    // L3: CDN 缓存
    return await this.cdn.get(key);
  }
}

2. 缓存键设计

// 缓存键规范
const CACHE_KEYS = {
  user: (id: string) => `user:${id}`,
  task: (id: string) => `task:${id}`,
  explore: (category: string, page: number) => `explore:${category}:${page}`,
  analytics: (date: string) => `analytics:${date}`,
};

速率限制配置

1. 基于用户层级的限制

// src/infrastructure/ratelimit/tier-limits.ts
export const TIER_LIMITS = {
  free: {
    requests: { limit: 10, window: "1h" },
    imageGeneration: { limit: 5, window: "1d" },
    videoGeneration: { limit: 1, window: "1d" },
    storage: { limit: 100 * 1024 * 1024 }, // 100MB
  },
  pro: {
    requests: { limit: 100, window: "1h" },
    imageGeneration: { limit: 50, window: "1d" },
    videoGeneration: { limit: 10, window: "1d" },
    storage: { limit: 5 * 1024 * 1024 * 1024 }, // 5GB
  },
  premium: {
    requests: { limit: 1000, window: "1h" },
    imageGeneration: { limit: 500, window: "1d" },
    videoGeneration: { limit: 100, window: "1d" },
    storage: { limit: 50 * 1024 * 1024 * 1024 }, // 50GB
  },
};

2. 实现示例

// src/middleware/rate-limit.ts
export async function rateLimitMiddleware(
  request: Request,
  env: Env,
  ctx: ExecutionContext
) {
  const userId = getUserId(request);
  const userTier = await getUserTier(userId);
  const limits = TIER_LIMITS[userTier];

  const key = `ratelimit:${userId}:requests`;
  const current = await env.QUOTA.get(key);

  if (current >= limits.requests.limit) {
    return new Response("Rate limit exceeded", { status: 429 });
  }

  await env.QUOTA.put(key, current + 1, {
    expirationTtl: parseWindow(limits.requests.window),
  });
}

监控和日志

1. 结构化日志

// src/infrastructure/monitoring/logger.ts
export class Logger {
  log(level: string, message: string, meta?: any) {
    const entry = {
      timestamp: new Date().toISOString(),
      level,
      message,
      ...meta,
      environment: env.ENVIRONMENT,
    };

    console.log(JSON.stringify(entry));
  }
}

2. 性能监控

// src/infrastructure/monitoring/performance.ts
export class PerformanceMonitor {
  async trackAPICall(endpoint: string, fn: Function) {
    const start = Date.now();
    try {
      const result = await fn();
      const duration = Date.now() - start;

      // 记录到分析存储
      await this.recordMetric({
        endpoint,
        duration,
        status: "success",
        timestamp: new Date().toISOString(),
      });

      return result;
    } catch (error) {
      const duration = Date.now() - start;
      await this.recordMetric({
        endpoint,
        duration,
        status: "error",
        error: error.message,
        timestamp: new Date().toISOString(),
      });
      throw error;
    }
  }
}

安全配置

1. API 认证

// src/middleware/auth.ts
export async function authMiddleware(
  request: Request,
  env: Env
): Promise<User | null> {
  const token = request.headers.get("Authorization")?.replace("Bearer ", "");

  if (!token) {
    throw new UnauthorizedError("No token provided");
  }

  try {
    // 验证 Firebase ID Token
    const decodedToken = await admin.auth().verifyIdToken(token);
    return {
      uid: decodedToken.uid,
      email: decodedToken.email,
      // ... 其他用户信息
    };
  } catch (error) {
    throw new UnauthorizedError("Invalid token");
  }
}

2. 输入验证

// 使用 Zod 进行严格的输入验证
import { z } from "zod";

export const ImageGenerationSchema = z.object({
  prompt: z.string().min(1).max(1000),
  style: z.enum(["realistic", "artistic", "cartoon"]).optional(),
  aspectRatio: z.enum(["1:1", "16:9", "9:16"]).default("1:1"),
  quality: z.enum(["standard", "high"]).default("standard"),
});

部署配置

1. 生产环境变量

# 设置生产环境密钥
pnpm wrangler secret put FIREBASE_PRIVATE_KEY
pnpm wrangler secret put OPENAI_API_KEY
pnpm wrangler secret put GOOGLE_AI_API_KEY
pnpm wrangler secret put FAL_KEY
pnpm wrangler secret put API_SECRET_KEY

2. 自定义域名

# 添加自定义域名
pnpm wrangler domains add api.yourdomain.com

# 配置路由
pnpm wrangler routes add api.yourdomain.com/* appsolve-backend

3. 环境隔离

// wrangler.jsonc
{
  "environments": {
    "staging": {
      "name": "appsolve-backend-staging",
      "vars": {
        "ENVIRONMENT": "staging"
      }
    },
    "production": {
      "name": "appsolve-backend",
      "vars": {
        "ENVIRONMENT": "production"
      }
    }
  }
}

故障排除

1. 常见错误

Firebase 认证失败

# 检查服务账号密钥
echo $FIREBASE_PRIVATE_KEY | base64 -d

# 验证项目 ID
firebase projects:list

KV 存储问题

# 列出所有 KV 命名空间
pnpm wrangler kv:namespace list

# 检查 KV 内容
pnpm wrangler kv:key list --namespace-id=xxx

R2 上传失败

# 检查存储桶
pnpm wrangler r2 bucket list

# 验证 CORS 配置
pnpm wrangler r2 bucket cors get media-storage

2. 性能优化

  • 使用 waitUntil() 处理非关键任务
  • 实现请求合并减少 API 调用
  • 使用 Cloudflare Cache API 缓存响应
  • 优化图片和视频的 CDN 分发

下一步