Skip to content

E13 前端部署与运维(SRE) ​

目标:掌握前端应用的部署、发布、监控、容灾和容量管理,保障线上服务稳定可用。


核心要点(TL;DR) ​

  • 前端部署不只是把文件上传到 CDN,还包括缓存策略、回滚、灰度和可观测性。
  • SRE 的核心是用工程化手段提升系统可靠性,而不是靠人力值守。
  • 发布策略决定风险:全量、灰度、蓝绿、金丝雀、A/B 测试各有适用场景。
  • 可观测性三大支柱:日志、指标、链路追踪。
  • 容灾和回滚能力比发布速度更重要。
  • SLA/SLO/SLI 是定义可靠性的量化工具,错误预算指导发布节奏。
  • 前端监控需要 RUM(真实用户监控)和 Synthetic(合成监控)相结合。
  • 环境变量注入分构建时和运行时两种模式,推荐混合使用。
  • 回滚不是重新部署,应有自动化的一键回滚机制。

1. 前端部署基础 ​

1.1 部署流程 ​

构建产物 -> 静态资源上传 -> CDN 刷新 -> DNS/路由切换 -> 验证 -> 监控

1.2 静态资源托管 ​

  • 对象存储:OSS/S3/MinIO
  • CDN:加速静态资源分发
  • 边缘节点:Cloudflare、Vercel Edge、AWS CloudFront

1.3 缓存策略 ​

资源类型缓存策略说明
HTMLno-cache / 短缓存(0-5 min)保证最新入口,SPA 路由兜底
JS/CSS(带 hash)长期缓存(1年 immutable)文件名变化自动失效
图片/字体/媒体长期缓存(1年)不常变化,通过文件名版本化
API 响应(BFF)按需缓存(CDN/Service Worker)根据接口特性配置
第三方 SDK长期 + Subresource Integrity避免篡改风险

缓存策略核心原则:

  • 带 hash 的资源使用 Cache-Control: public, max-age=31536000, immutable
  • HTML 入口使用 Cache-Control: no-cache 配合 ETag / Last-Modified
  • 所有资源都应启用 gzip / brotli 压缩
  • Service Worker 可实现更细粒度的缓存策略

1.4 对象存储与 CDN 配置示例(OSS + CDN) ​

yaml
# 阿里云 OSS 静态网站托管配置
Bucket:
  Name: my-app-prod
  Access: public-read
  StaticWebsite:
    Index: index.html
    Error: index.html          # SPA 路由兜底
  Lifecycle:
    - prefix: builds/
      expire_days: 90          # 历史构建版本自动清理

CDN:
  Domain: static.example.com
  Origin: my-app-prod.oss-cn-hangzhou.aliyuncs.com
  CacheRules:
    - pattern: *.html
      TTL: 0                   # no-cache
    - pattern: *.js,*.css
      TTL: 365d                # hash 文件名,长期缓存
    - pattern: *.png,*.jpg,*.svg,*.woff2
      TTL: 365d
  Preload:
    enabled: true              # 每次部署后预热热门资源

1.5 SPA 路由历史模式下的 Nginx 配置 ​

nginx
server {
    listen 80;
    server_name example.com;
    root /usr/share/nginx/html;

    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
    gzip_min_length 1024;
    gzip_static on;

    location ~* \.(?:css|js|woff2?|svg|png|jpg|jpeg|gif|ico|webp)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    location ~* \.html$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }

    # SPA 路由历史模式:所有非文件请求返回 index.html
    location / {
        try_files $uri $uri/ /index.html;
    }

    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
}

1.6 .dockerignore 最佳实践 ​

dockerignore
node_modules
.git
.gitignore
*.md
src/
.env
.env.local
.editorconfig
.eslintrc*
.prettierrc*
tsconfig.json
tests/
e2e/
__tests__/
coverage/

1.6.5 环境变量注入模式(Build-time vs Runtime) ​

前端环境变量的注入有两种模式,理解它们的差异对部署架构设计至关重要。

维度构建时注入(Build-time)运行时注入(Runtime)
时机构建阶段(npm run build)容器启动时 / CDN 部署后
方式webpack/Vite 的 define 替换服务器注入 script 标签 / ConfigMap
产物差异不同环境生成不同镜像/产物同一份构建产物,运行时注入配置
优势性能最优,无用代码被 tree-shaking一次构建到处运行,便于 QA 验证
劣势每套环境都需要单独构建配置不能参与 tree-shaking
适用场景API Base URL、域名配置、权限控制个性化配置、A/B 参数、灰度标签
安全级别高(不在客户端暴露构建过程)配置值在 HTML 中可见

推荐策略:混合使用

构建时注入:使用 define 替换编译时常量。适合版本号、构建时间、Git Commit 等固定值。

typescript
// vite.config.ts - 构建时注入
export default defineConfig({
  define: {
    __BUILD_TIME__: JSON.stringify(new Date().toISOString()),
    __GIT_COMMIT__: JSON.stringify(process.env.GIT_COMMIT),
    __APP_VERSION__: JSON.stringify(process.env.npm_package_version),
  }
});

运行时注入:在返回 HTML 时由服务器注入动态配置。适合 API 域名、环境标识、Feature Flag 等可变值。

html
<!-- index.html - 运行时占位符,服务器在返回前替换 -->
<!DOCTYPE html>
<html>
<head>
  <script>
    window.__ENV__ = {
      API_BASE_URL: '&#123;&#123;API_BASE_URL&#125;&#125;',
      APP_ENV: '&#123;&#123;APP_ENV&#125;&#125;',
      CDN_DOMAIN: '&#123;&#123;CDN_DOMAIN&#125;&#125;'
    };
  </script>
</head>
</html>

Nginx 运行时替换:

nginx
# 使用 sub_filter 模块替换占位符
sub_filter_once on;
sub_filter '&#123;&#123;API_BASE_URL&#125;&#125;' 'https://api.example.com';
sub_filter '&#123;&#123;APP_ENV&#125;&#125;' 'production';

构建时 vs 运行时决策树:

配置值需要在构建时确定吗?
  ├── 是 → 构建时注入(define/import.meta.env)
  │    示例:API基础域名、Sentry DSN(区分环境)
  └── 否 → 运行时注入(服务器注入 / ConfigMap)
        ├── 需要热更新? → WebSocket / Server-Sent Events
        └── 不需要 → HTML 占位符替换 / K8s ConfigMap

1.7 Docker 多阶段构建前端镜像 ​

dockerfile
# ---- 阶段一:构建 ----
FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile

COPY . .
ARG APP_ENV=production
RUN echo "VITE_APP_ENV=${APP_ENV}" >> .env.production
RUN npm run build

# ---- 阶段二:运行 ----
FROM nginx:1.25-alpine
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
COPY --from=builder /app/dist /usr/share/nginx/html

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

1.7.1 Dockerfile 逐段详解 ​

阶段一:构建阶段

dockerfile
FROM node:20-alpine AS builder
WORKDIR /app

COPY package.json pnpm-lock.yaml ./
RUN corepack enable && pnpm install --frozen-lockfile
  • 使用 node:20-alpine 作为基础镜像,体积小(~120MB),安全性高
  • 先复制依赖配置文件,再执行安装 —— 利用 Docker 层缓存加速
  • --frozen-lockfile 确保锁定文件一致,防止依赖版本漂移
dockerfile
COPY . .
ARG APP_ENV=production
RUN echo "VITE_APP_ENV=${APP_ENV}" >> .env.production
RUN npm run build
  • ARG 允许通过 --build-arg 传入环境变量,实现多环境构建
  • 构建产物输出到 /app/dist

阶段二:运行阶段

dockerfile
FROM nginx:1.25-alpine
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d/
COPY --from=builder /app/dist /usr/share/nginx/html
  • 使用 nginx:1.25-alpine(~25MB)作为运行镜像
  • --from=builder 仅从构建阶段复制产物,构建工具和源码不进入最终镜像
  • 最终镜像只包含:nginx 二进制 + 配置文件 + 静态文件

镜像大小对比:

方案镜像大小说明
单阶段(node 镜像运行 nginx)~1.2GB包含全部 node 工具链
单阶段(nginx 镜像手动构建)~400MB仍包含构建缓存
多阶段构建~25MB仅包含运行时文件

1.8 构建时 vs 运行时:Env 注入总结 ​

推荐策略:

  • 构建时注入:版本号、构建时间、Git Commit SHA(固定不变)
  • 运行时注入:API Base URL、环境标识、Feature Flag、CDN 域名
  • 混合使用:一次构建 + 运行时注入 = 同一份产物部署到多环境

2. 发布策略详解 ​

2.1 策略对比总览 ​

策略速度风险成本回滚速度适用场景
全量发布快高低中等热修复、低风险变更
灰度发布慢中低快功能逐步开放
金丝雀发布中等低中快重大版本发布
蓝绿发布快极低高极快核心服务、支付等关键系统
A/B 测试慢低中N/A业务验证、UI 实验
滚动发布中等中低慢后端微服务,前端少用

2.1.1 滚动发布(Rolling Update)详解 ​

原理:逐步替换运行中的实例,每次只更新一部分,保持服务不中断。后端微服务常用,前端 SSR 场景也会用到。

滚动更新流程(以 K8s 5 副本为例):

maxSurge: 1, maxUnavailable: 1

T0: [v1] [v1] [v1] [v1] [v1]   全部旧版本
T1: [v1] [v1] [v1] [v1] [v2]   启动一个新 v2 实例
T2: [v1] [v1] [v1] [v2] [v2]   停止一个 v1 实例
T3: [v1] [v1] [v2] [v2] [v2]
T4: [v1] [v2] [v2] [v2] [v2]
T5: [v2] [v2] [v2] [v2] [v2]   全部替换完成

K8s 滚动更新配置:

yaml
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 5
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  minReadySeconds: 10         # 新 Pod 就绪后等待 10 秒再继续
  progressDeadlineSeconds: 300 # 更新超时时间

滚动回滚命令:

bash
# 回滚到上一个版本
kubectl rollout undo deployment/frontend -n production

# 回滚到指定版本
kubectl rollout undo deployment/frontend -n production --to-revision=3

# 查看发布历史
kubectl rollout history deployment/frontend -n production

策略选择指南:

部署方式推荐策略原因
纯静态前端(CDN 托管)蓝绿 / 全量只需切换 CDN 指向的目录版本
SSR 前端(K8s 部署)滚动 / 金丝雀实例逐步替换,观察内存和 CPU
BFF 层(Node.js)滚动 + 金丝雀需要监控请求延迟和错误率
重大 UI 重构蓝绿 + Feature Flag瞬时全量切换 + 功能级别 kill switch

2.2 蓝绿发布(Blue-Green Deploy) ​

原理:准备两套完全独立的、与生产环境镜像的环境。蓝环境(当前生产)和绿环境(新版本)同时运行,通过路由/负载均衡器切换流量。

拓扑示意:

                   +----------------+
                   |  Load Balancer |
                   |  (Router/Nginx)|
                   +-------+--------+
                           |
              +------------+------------+
              |                         |
       +------v------+         +------v------+
       |  Blue (v1)  |         | Green (v2)  |
       |  (current)  |         |  (staging)  |
       +-------------+         +-------------+

步骤:

  1. 部署 v2 到绿环境,完整 CI/CD 流程一次性完成
  2. 在绿环境运行集成测试和烟雾测试
  3. 切换负载均衡器,将 100% 流量导向绿环境
  4. 监控 15-30 分钟,观察错误率和性能指标
  5. 如有问题,立即切回蓝环境(秒级回滚)
  6. 确认稳定后,蓝环境保留作为下一次回滚目标

优点:回滚极快(DNS/路由切换即可)、零停机、环境隔离彻底 缺点:资源成本翻倍、DB 兼容性需要额外关注、切换瞬间可能有短暂不一致

2.3 金丝雀发布(Canary Release) ​

原理:新版本部署到一小部分节点或用户子集,验证稳定后逐步扩大比例。

流量切分阶段:

阶段   | 金丝雀 | 稳定版 | 持续时间  | 验证内容
------|---------|--------|-----------|---------
1     |   1%    |  99%   |  15 min   | 错误率、崩溃率
2     |   5%    |  95%   |  30 min   | Web Vitals、CPU/内存
3     |   20%   |  80%   |  30 min   | 业务指标、转化率
4     |   50%   |  50%   |  30 min   | 全面对比
5     |  100%   |   0%   |  -        | 完成发布

前端金丝雀实现方式:

  • CDN 层面:通过权重 DNS 或边缘逻辑分流
  • 网关层面:Nginx lua 脚本根据 Cookie/Header 分流
  • 应用层面:Feature Flag SDK 控制

Nginx 权重分流示例:

nginx
upstream frontend {
    server 192.168.1.10 weight=95;  # 稳定版
    server 192.168.1.11 weight=5;   # 金丝雀
}

2.4 全量发布 ​

全量发布的危险信号:

  • 未经过灰度验证的重大变更(改架构、换框架)
  • 前端资源与后端接口不兼容的更新
  • 缓存策略、CDN 配置变更未验证
  • 缺少自动化回滚预案

安全全量发布的必要条件:

  1. 完善的自动化测试覆盖
  2. 前 5 分钟的错误率 / 性能自动告警
  3. 一键回滚能力(保留上一版本产物)
  4. 发布窗口期(非高峰时段)

2.5 A/B 测试 ​

A/B 测试与灰度发布的区别:

维度灰度发布A/B 测试
目的降低风险验证假设
持续时间数小时-数天数天-数周
流量分配逐步到 100%固定比例
评估指标稳定性业务转化率
结束条件确认稳定即全量统计显著后判定

A/B 测试分流方案:

javascript
function getAbVariant(userId, experimentName) {
  const hash = hashCode(experimentName + ':' + userId);
  return hash % 100 < 50 ? 'control' : 'treatment';
}

2.6 Feature Flag(特性开关) ​

Feature Flag 层级:

级别 | 作用域     | 生命周期   | 示例
-----|-----------|-----------|------
发布 | Release   | 短(天)  | 功能上线开关
实验 | Experiment| 中(周)  | A/B 测试变体
运维 | Ops       | 长(月)  | 降级开关、kill switch
权限 | Permission| 永久      | 白名单用户功能

推荐方案:

  • 自研:简单 localStorage 开关 + 接口下发配置
  • 开源:Unleash、LaunchDarkly
  • 轻量:基于 URL Query 参数覆写

Feature Flag 代码示例:

typescript
type FeatureFlags = {
  newHomePage: boolean;
  aiRecommendation: boolean;
  darkModeV2: boolean;
};

class FeatureFlagService {
  private flags: FeatureFlags = {};
  private overrides: Partial<FeatureFlags> = {};

  async init() {
    const resp = await fetch('/config/feature-flags.json');
    const remote = await resp.json();
    const params = new URLSearchParams(location.search);
    params.forEach((value, key) => {
      if (key.startsWith('ff_')) {
        const flagName = key.replace('ff_', '') as keyof FeatureFlags;
        this.overrides[flagName] = value === '1';
      }
    });
    this.flags = { ...remote, ...this.overrides };
  }

  isEnabled(flag: keyof FeatureFlags): boolean {
    return this.flags[flag] ?? false;
  }
}

3. CI/CD 流水线设计 ​

3.1 流水线阶段 ​

完整的现代前端 CI/CD 流水线包括十个阶段:

代码提交
   |
   v
[1] 代码质量 ── Lint + Prettier + TypeScript 严格模式
   |
   v
[2] 单元测试 ── Jest/Vitest + 覆盖率门禁 >= 80%
   |
   v
[3] 安全扫描 ── npm audit + Snyk/Trivy 依赖扫描 + SAST
   |
   v
[4] 构建 ── 多环境构建(staging/production)+ 产物大小对比
   |
   v
[5] 制品签名 ── 哈希校验 + 签名确保完整性
   |
   v
[6] 制品上传 ── 上传到对象存储 / 镜像仓库
   |
   v
[7] Staging 部署 ── 自动部署到预发布环境
   |
   v
[8] E2E 测试 ── Playwright/Cypress + Lighthouse CI
   |
   v
[9] 生产部署 ── 灰度发布(1% → 5% → 20% → 50% → 100%)
   |
   v
[10] 监控验证 ── 错误率 + Web Vitals + CDN 缓存命中率
   |
   v
发布完成

3.2 GitHub Actions 完整工作流 ​

yaml
# .github/workflows/deploy.yml
name: Frontend CI/CD

on:
  push:
    branches: [main, release/*]
  pull_request:
    branches: [main]

env:
  NODE_VERSION: "20"
  PNPM_VERSION: "9"
  REGISTRY: ghcr.io

jobs:
  quality:
    name: Code Quality
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: $&#123;&#123; env.PNPM_VERSION &#125;&#125;
      - uses: actions/setup-node@v4
        with:
          node-version: $&#123;&#123; env.NODE_VERSION &#125;&#125;
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm lint
      - run: pnpm typecheck
      - run: pnpm test -- --coverage

  build:
    name: Build and Package
    needs: quality
    runs-on: ubuntu-latest
    strategy:
      matrix:
        env: [staging, production]
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
        with:
          version: $&#123;&#123; env.PNPM_VERSION &#125;&#125;
      - uses: actions/setup-node@v4
        with:
          node-version: $&#123;&#123; env.NODE_VERSION &#125;&#125;
          cache: pnpm
      - run: pnpm install --frozen-lockfile
      - run: pnpm build:"$&#123;&#123; matrix.env &#125;&#125;"
      - name: Upload dist artifacts
        uses: actions/upload-artifact@v4
        with:
          name: dist-$&#123;&#123; matrix.env &#125;&#125;
          path: dist/
      - name: Build Docker image
        run: |
          docker build \
            --build-arg APP_ENV=$&#123;&#123; matrix.env &#125;&#125; \
            -t $&#123;&#123; env.REGISTRY &#125;&#125;/my-app:$&#123;&#123; matrix.env &#125;&#125;-$&#123;&#123; github.sha &#125;&#125; \
            .

  deploy-production:
    name: Deploy to Production
    needs: build
    runs-on: ubuntu-latest
    environment: production
    concurrency: production-deploy
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist-production
      - name: Sync to Production S3
        run: |
          aws s3 sync dist/ s3://my-app-prod/current/ --delete
          aws s3 cp dist/index.html s3://my-app-prod/current/index.html \
            --cache-control "no-cache, no-store, must-revalidate"
      - name: CDN Cache Invalidation
        run: |
          aws cloudfront create-invalidation \
            --distribution-id $&#123;&#123; secrets.CF_DIST_ID_PROD &#125;&#125; \
            --paths "/*"
      - name: Smoke Test
        run: curl -sSf -o /dev/null -w "%{http_code}" https://example.com | grep 200

3.3 发布门禁(Quality Gates) ​

建议在 CI 中设置的门禁:

  • Lint 零错误、TypeScript 严格模式通过
  • 单元测试覆盖率 >= 80%(核心模块 >= 90%)
  • 构建产物大小对比(增量超过 10% 需人工审批)
  • 安全检查:无高危依赖漏洞 (npm audit / pnpm audit)
  • Lighthouse 性能评分 >= 85(移动端)
  • E2E 测试全部通过

增量大小检测示例:

bash
#!/bin/bash
# scripts/check-bundle-size.sh
MAX_SIZE_KB=500
current_size=$(du -sk dist/assets/main-*.js | cut -f1)
if [ "$current_size" -gt "$MAX_SIZE_KB" ]; then
  echo "Bundle size ${current_size}KB exceeds limit ${MAX_SIZE_KB}KB"
  exit 1
fi
echo "Bundle size: ${current_size}KB - OK"

4. Kubernetes 前端部署基础 ​

4.1 为什么前端需要 K8s ​

传统前端只需要静态托管,但以下场景需要 K8s:

  • 前端应用包含 SSR(服务端渲染)
  • 需要精细化流量管理(灰度、分流)
  • 与后端 BFF 统一部署管理
  • 自建 CI/CD 需要容器化编排

4.2 Deployment 示例 ​

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
  namespace: production
  labels:
    app: frontend
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
        - name: nginx
          image: ghcr.io/myorg/frontend:latest
          ports:
            - containerPort: 80
          resources:
            requests:
              memory: 128Mi
              cpu: 100m
            limits:
              memory: 256Mi
              cpu: 200m
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 3
            periodSeconds: 5

4.3 Service 示例 ​

yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  namespace: production
spec:
  type: ClusterIP
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

4.4 Ingress 示例 ​

yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: frontend-ingress
  namespace: production
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-read-timeout: "30"
spec:
  tls:
    - hosts:
        - example.com
      secretName: example-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80

4.5 ConfigMap 注入前端配置 ​

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-config
  namespace: production
data:
  config.js: |
    window.__ENV__ = {
      API_BASE_URL: 'https://api.example.com',
      APP_ENV: 'production',
      SENTRY_DSN: 'https://xxx@sentry.example.com/1',
      FEATURE_FLAGS: { newHome: true, aiRec: false }
    };
yaml
# 在 Deployment 中挂载 ConfigMap
# volumeMounts:
#   - name: config
#     mountPath: /usr/share/nginx/html/config.js
#     subPath: config.js
# volumes:
#   - name: config
#     configMap:
#       name: frontend-config

4.6 HPA(水平自动扩缩容) ​

yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: frontend-hpa
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: frontend
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

4.7 K8s 蓝绿部署 Service Mesh 方案 ​

yaml
# 使用 Service 的 selector 切换蓝绿
apiVersion: v1
kind: Service
metadata:
  name: frontend
  namespace: production
spec:
  selector:
    app: frontend
    version: green   # 切换为 blue 即回滚
  ports:
    - port: 80

5. CDN 架构与缓存策略 ​

5.1 CDN 架构层级 ​

                       +------------------+
                       |   Origin Server   |
                       | (OSS/S3/Nginx)    |
                       +--------+---------+
                                |
                       +--------v---------+
                       |   Origin Shield   |
                       | (回源收敛层)      |
                       +--------+---------+
                                |
          +---------------------+----------------------+
          |                     |                      |
   +------v------+      +------v------+      +------v------+
   |   Edge L1   |      |   Edge L1   |      |   Edge L1   |
   | (pop-beijing)|     | (pop-shanghai)|    | (pop-shenzhen)|
   +-------------+      +-------------+      +-------------+

5.2 回源收敛与 Origin Shield ​

Origin Shield 作用:

  • 所有边缘节点的回源请求先到达 Origin Shield,再由 Shield 回源站
  • 减少源站请求量(缓存命中率更高)
  • 保护源站不被突发流量打垮
  • 降低回源带宽成本

配置要点:

yaml
CDN:
  OriginShield:
    enabled: true
    region: cn-hangzhou       # Shield 区域,选择接近源站的区域
    maxCacheSize: 100GB
  CacheLayer:
    - name: Edge
      TTL: 1h                 # 边缘节点缓存 1 小时
    - name: Shield
      TTL: 24h                # Shield 层缓存 24 小时

5.3 缓存失效策略 ​

策略方式适用场景延迟
精确刷新指定文件路径单个文件更新秒级
目录刷新指定目录前缀批量更新分钟级
全站刷新/*重大版本发布分钟级
版本号刷新URL 追加版本参数无 CDN 操作权限时即时
预加载主动预热文件大版本上线前提前完成

缓存刷新策略建议:

  • 日常发布:只刷新 index.html(推荐精确路径刷新)
  • 大版本发布:预热全部静态资源 + 刷新 HTML
  • 紧急回滚:立即刷新全站 + 预热回滚版本资源

AWS CloudFront 刷新脚本:

bash
#!/bin/bash
# scripts/refresh-cdn.sh
DIST_ID=$1
PATHS=${2:-'/*'}
aws cloudfront create-invalidation \
  --distribution-id $DIST_ID \
  --paths $PATHS
echo "Invalidation created for distribution $DIST_ID"

5.4 边缘计算(Edge Computing) ​

CDN 边缘节点不仅仅是缓存,还可以执行计算:

Cloudflare Workers 示例 - A/B 测试分流:

javascript
// Cloudflare Worker: A/B testing at the edge
const AB_CONFIG = {
  control: { weight: 0.5, upstream: 'https://v1.example.com' },
  treatment: { weight: 0.5, upstream: 'https://v2.example.com' }
};

async function handleRequest(request) {
  const cookie = request.headers.get('Cookie') || '';
  let variant = cookie.match(/variant=(\w+)/)?.[1];

  if (!variant) {
    const rand = Math.random();
    variant = rand < AB_CONFIG.control.weight ? 'control' : 'treatment';
  }

  const upstream = AB_CONFIG[variant].upstream;
  const response = await fetch(upstream + new URL(request.url).pathname);

  const newResponse = new Response(response.body, response);
  newResponse.headers.set('Set-Cookie', `variant=${variant}; Path=/; Max-Age=3600`);
  newResponse.headers.set('X-Variant', variant);
  return newResponse;
}

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request));
});

5.5 CDN 安全配置 ​

yaml
CDN Security:
  WAF:
    enabled: true
    rules:
      - SQL注入防护: on
      - XSS防护: on
      - CC攻击防护: on
      - 频率限制: 1000 req/min per IP
  Referer防盗链:
    type: blacklist/whitelist
    allowEmpty: false
    domains:
      - '*.example.com'
  IP频率限制:
    threshold: 100
    period: 10s

6. 静态托管平台对比与选型 ​

6.1 主流平台对比 ​

特性VercelNetlifyCloudflare PagesAWS S3 + CloudFront
免费额度100GB带宽/月100GB带宽/月无限带宽按量计费
全球节点100+250+330+400+
边缘函数Vercel EdgeNetlify EdgeCloudflare WorkersLambda@Edge
部署方式Git自动Git自动Git自动CI/CD手动
预览部署自动生成自动生成自动生成需自建
自定义域名支持支持支持支持
SSL证书自动自动自动ACM免费
构建限制45min/月(免费)300min/月(免费)500次/月(免费)无限制
回滚一键一键一键需自建
适合场景SSR/SSG应用静态站点/博客静态站点/API企业生产环境

6.2 选型建议 ​

  • 初创项目/个人项目:Vercel 或 Cloudflare Pages,零配置、快速上手
  • 企业级应用:S3 + CloudFront,成本可控、安全合规、可定制
  • 高度动态站点:Vercel(Next.js)或自建 K8s,SSR 需要更灵活的计算
  • 内容型网站:Cloudflare Pages,全球节点最多、带宽免费
  • 需要预览部署和团队协作:Vercel 或 Netlify 体验最佳

6.3 S3 + CloudFront 完整部署脚本 ​

bash
#!/bin/bash
set -euo pipefail

BUCKET='my-app-prod'
DISTRIBUTION_ID='E1234567890ABC'
BUILD_DIR='./dist'
VERSION=$(git rev-parse --short HEAD)

echo "Uploading version $VERSION to S3..."

# 上传带 hash 的资源(长期缓存)
aws s3 sync $BUILD_DIR/assets s3://$BUCKET/current/assets/ \
  --cache-control 'public, max-age=31536000, immutable' \
  --exclude '*.map'

# 上传 HTML(禁止缓存)
aws s3 cp $BUILD_DIR/index.html s3://$BUCKET/current/index.html \
  --cache-control 'no-cache, no-store, must-revalidate'

# CDN 刷新
aws cloudfront create-invalidation \
  --distribution-id $DISTRIBUTION_ID \
  --paths '/index.html' '/assets/*'

echo "Deploy complete: https://example.com"

7. 可观测性与监控(扩展) ​

7.1 RUM(Real User Monitoring) ​

核心指标采集:

javascript
// Web Vitals 采集示例
import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';

function sendToAnalytics(metric) {
  const body = {
    name: metric.name,
    value: metric.value,
    rating: metric.rating,
    delta: metric.delta,
    url: location.pathname,
    userAgent: navigator.userAgent,
    timestamp: Date.now()
  };
  // 使用 sendBeacon 确保卸载时也能发送
  navigator.sendBeacon('/api/vitals', JSON.stringify(body));
}

onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);

RUM 数据应用:

  • LCP > 2.5s 触发性能告警
  • CLS > 0.1 触发布局偏移告警
  • 按版本、浏览器、地域、网络类型下钻分析
  • 发布前后自动对比 Web Vitals 变化

7.2 合成监控(Synthetic Monitoring) ​

使用 Checkly / Playwright 定时检查:

typescript
// synthetics/check.ts
import { test, expect } from '@playwright/test';

test('homepage loads within budget', async ({ page }) => {
  const start = Date.now();
  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  const loadTime = Date.now() - start;
  expect(loadTime).toBeLessThan(3000);

  // 检查关键元素
  await expect(page.locator('#app')).toBeVisible();
  await expect(page.locator('h1')).toHaveText('欢迎');

  // 检查控制台无错误
  const errors: string[] = [];
  page.on('console', msg => {
    if (msg.type() === 'error') errors.push(msg.text());
  });
  expect(errors.length).toBe(0);
});

7.3 错误追踪(Error Tracking) ​

Sentry 集成示例:

typescript
// sentry.ts
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';

Sentry.init({
  dsn: window.__ENV__.SENTRY_DSN,
  environment: window.__ENV__.APP_ENV,
  release: __APP_VERSION__,
  integrations: [new BrowserTracing()],
  tracesSampleRate: 0.1,           # 采样率 10%
  replaysSessionSampleRate: 0.01,  # Session replay 采样 1%
  replaysOnErrorSampleRate: 1.0,   # 错误时 100% 录制
  beforeSend(event) {
    # 过滤已知非关键错误
    if (event.exception?.values?.[0]?.type === 'ResizeObserver loop limit exceeded') {
      return null;
    }
    return event;
  }
});

错误分类与处理优先级:

P0 - 白屏、JS 崩溃、页面完全不可用 -> 立即告警(5分钟内响应)
P1 - 功能模块报错、API大面积失败 -> 快速响应(30分钟内)
P2 - 单个组件异常、非关键路径报错 -> 正常排期修复
P3 - 低影响告警、第三方 SDK 异常 -> 观察积累

7.4 告警规则设计 ​

前端核心告警规则:

指标告警阈值严重度聚合窗口
JS 错误率> 1%P05min
白屏率> 0.5%P05min
LCP> 3.0s 占比 > 5%P110min
API 错误率> 5%P15min
页面加载失败率> 2%P15min
带宽峰值> 预估 80%P210min
CDN 回源率> 10%P210min

告警疲劳避免策略:

  • 告警聚合:相同类型的告警合并为一条
  • 动静分离:夜间(非工作时间)告警降级为通知
  • 自动静默:已知维护窗口期自动静默告警
  • 依赖告警:CDN 有问题时,不要同时触发所有页面告警

8. 回滚策略与容灾能力 ​

8.1 回滚分类 ​

类型速度复杂度数据安全适用场景
代码回滚快(分钟级)低无影响功能 Bug、样式问题
CDN 回滚极快(秒级)低无影响缓存错误、资源损坏
DNS 切换中等(TTL 时间)中无影响全站切换、CDN 故障
K8s 回滚快(秒级)中无影响容器化部署回滚
Feature Flag极快(毫秒级)低无影响功能级 kill switch
数据库回滚慢(小时级)高有数据丢失风险后端变更,前端少用

8.2 代码回滚策略 ​

Git 回滚方式对比:

bash
# 方式一:git revert(推荐)
git revert <commit-hash>             # 生成一个反向提交
git push origin main

# 方式二:git reset(谨慎使用)
git reset --hard <previous-tag>      # 丢弃之后的所有提交
git push --force origin main         # 需要 force push

# 方式三:版本切换(S3 多版本)
aws s3 sync s3://my-app-prod/releases/v1.2.3/ s3://my-app-prod/current/

8.3 保留多版本制品 ​

S3 版本管理策略:

bash
# S3 存储结构
s3://my-app-prod/
  releases/
    v1.2.0/          # 当前稳定版
    v1.3.0/          # 新版本(刚刚发布)
    v1.1.0/          # 上一个稳定版(保留用于快速回滚)
  current/           # 符号链接指向当前版本

# 回滚即复制上一版本到 current
aws s3 sync s3://my-app-prod/releases/v1.2.0/ s3://my-app-prod/current/ --delete
aws cloudfront create-invalidation --distribution-id $DIST_ID --paths '/*'

8.4 数据库兼容性(前端发布关注点) ​

虽然前端不直接操作数据库,但以下场景需关注兼容性:

  • API 字段变更:新前端需要新的 API 字段时,后端必须先发布(向后兼容)
  • 蓝绿切换的 DB 兼容:新旧版本前端同时在线期间,API 必须同时兼容两种请求
  • LocalStorage Schema 变更:新版本写入新格式,旧版本读取旧格式,或清理旧数据

LocalStorage 兼容性示例:

typescript
const STORAGE_VERSION = 2;

function migrateStorage() {
  const version = parseInt(localStorage.getItem('schema_version') || '0');

  if (version < 1) {
    // v1: 旧格式清理
    localStorage.removeItem('old_cart_data');
    version = 1;
  }

  if (version < 2) {
    // v2: 迁移到新格式
    const oldData = JSON.parse(localStorage.getItem('cart') || '{}');
    const newData = { items: Object.values(oldData), version: 2 };
    localStorage.setItem('cart', JSON.stringify(newData));
    version = 2;
  }

  localStorage.setItem('schema_version', String(version));
}

9. SLA、SLO 与 SLI ​

9.1 概念定义 ​

术语含义示例
SLI(Service Level Indicator)服务水平指标(可量化的度量)页面加载时间、错误率
SLO(Service Level Objective)服务水平目标(目标值)99.9% 的请求 LCP < 2.5s
SLA(Service Level Agreement)服务水平协议(对外承诺)99.9% 可用性,否则赔偿

9.2 前端 SLI 指标 ​

核心前端 SLI:

  • 页面可用性:页面成功加载的请求占比
  • 加载性能:LCP <= 2.5s 的比例
  • 交互性能:INP <= 200ms 的比例
  • 视觉稳定性:CLS <= 0.1 的比例
  • JS 错误率:无错误的页面访问占比
  • API 成功率:前端发起的 API 请求成功率

9.3 前端 SLO 推荐值 ​

指标SLO测量窗口
页面可用性(白屏率)>= 99.95%30天滚动
LCP 达标率>= 90% 在 2.5s 内7天滚动
CLS 达标率>= 95% 在 0.1 内7天滚动
JS 错误率<= 0.5% 的访问有错误7天滚动
CDN 可用性99.99%30天滚动

9.4 错误预算(Error Budget) ​

计算公式:

错误预算 = (1 - SLO) * 总时间
例如:SLO = 99.9%,月度总时间 = 30 * 24 * 60 = 43200 分钟
可用错误预算 = 43200 * 0.001 = 43.2 分钟(不可用时间)

错误预算策略:

  • 预算充足(> 50% 剩余):可以正常发布
  • 预算紧张(20-50% 剩余):控制发布频率,加强测试
  • 预算耗尽(< 20% 剩余或为负):冻结发布,全力修复

9.5 SLO 监控仪表盘 ​

yaml
# Grafana / Datadog 告警规则示例
alert:
  - name: SLO Burn Rate Alert
    condition: >
    - 在 1 小时内消耗了 2% 的错误预算
    - 或者 6 小时内消耗了 5% 的错误预算
    - 或者 30 天内消耗了 100% 的错误预算
    severity: critical
    notification: on-call

10. 故障演练与应急预案 ​

10.1 前端混沌工程原则 ​

混沌工程不是破坏,而是通过受控实验验证系统的容错能力。 前端混沌工程关注的是:

  • 当 CDN 节点故障时,用户是否还能访问?
  • 当 API 接口超时时,页面是否优雅降级?
  • 当第三方 SDK 加载失败时,主功能是否受影响?
  • 当网络从 4G 降为 2G 时,应用是否可用?

10.2 故障场景库 ​

故障场景演练方式预期结果严重度
CDN 节点宕机模拟 DNS 解析到备用源自动切换到备用 CDNP0
API 全部超时Mock 接口返回 5xx降级页面 + 重试机制P0
主 JS 加载失败拦截 main.js 请求 404展示静态兜底页面P0
第三方 SDK 挂掉拦截 analytics.js不影响主流程P1
图片 CDN 不可用Mock 图片返回 403展示占位图P2
LocalStorage 满填充 5MB 数据优雅 catch 异常P2
弱网环境Chrome DevTools 限速Service Worker 离线缓存P1
CPU 高负载限制 CPU 线程数滚动性能不崩溃P2

10.3 故障注入工具与实践 ​

使用 Playwright 模拟网络故障:

typescript
import { test } from '@playwright/test';

test('CDN failure should show fallback page', async ({ page }) => {
  // 拦截所有 CSS 请求返回 500
  await page.route('**/*.css', route => {
    route.abort();
  });

  await page.goto('https://example.com');
  // 验证页面仍然有基本内容
  await expect(page.locator('body')).toBeVisible();
  await expect(page.locator('.fallback-message')).toBeVisible();
});

test('API failure should show error state', async ({ page }) => {
  await page.route('**/api/**', route => {
    route.fulfill({
      status: 500,
      contentType: 'application/json',
      body: JSON.stringify({ error: 'Server Error' })
    });
  });

  await page.goto('https://example.com');
  await expect(page.locator('.error-boundary')).toBeVisible();
});

10.4 应急预案(Runbook) ​

故障响应流程:

1. 发现(Detection)
   - 自动告警触发:错误率突增、白屏率上升、LCP 恶化
   - 用户反馈:客服群/工单系统

2. 响应(Response)
   - 值班人员确认告警(5min内)
   - 判断影响范围:全局/部分用户/特定页面
   - 公告:在状态页更新(status.example.com)

3. 止损(Mitigation)
   - 优先回滚/降级,不要花时间查 root cause
   - 执行预演过的回滚脚本
   - 如无法回滚,执行 Feature Flag 功能降级

4. 排查(Investigation)
   - 查看 Sentry 错误采样
   - 查看 RUM 性能曲线变化
   - 对比最近发布变更

5. 恢复(Resolution)
   - 确认问题已修复
   - 持续监控 30 分钟

6. 复盘(Postmortem)
   - 编写故障报告(5 Why 分析法)
   - 制定改进措施并跟踪闭环

10.5 日常演练计划 ​

频率演练内容参与人
每月三分之一的故障场景轮换演练值班团队
每季度全流程故障模拟(Game Day)全体 SRE
每半年容灾切换演练(跨区域)基础架构团队
发布前新功能降级验证开发团队

10.6 值班轮换制度(On-Call Rotation) ​

值班模型:

                    +---------------+
                    |   SRE Team    |
                    +-------+-------+
                            |
      +---------------------+----------------------+
      |                     |                      |
+------v------+      +------v------+      +------v------+
|   Primary   |      |  Secondary  |      |  Escalation  |
|   (1 week)  |      |   (1 week)  |      |  (Manager)   |
+-------------+      +-------------+      +-------------+

值班规则:

  • 轮换周期:每周一轮换(周一早上交接)
  • 响应时间:P0 告警 5 分钟内响应,P1 告警 15 分钟内响应
  • 交接内容:本周告警统计、未关闭事件、已知问题、版本发布计划

值班工具链:

  • PagerDuty / OpsGenie:告警通知与排班
  • Status Page:对外状态页(status.example.com)
  • Escalation Policy:Primary 超时 -> Secondary -> Engineering Manager

10.7 事后复盘模板(Postmortem Template) ​

P0/P1 故障后 48 小时内完成事后复盘。目的是找出系统性改进点,而非追责。

markdown
# 故障报告

## 基本信息
- **故障编号**:INC-YYYY-MM-DD-XXX
- **标题**:[简短描述]
- **日期**:YYYY-MM-DD
- **持续时间**:[开始] -> [结束](共计 XX 分钟)
- **严重度**:P0 / P1
- **值班人员**:@name
- **影响范围**:影响用户数 / 页面 / 功能

## 时间线

| 时间 | 事件 |
|------|------|
| HH:MM | 告警触发 |
| HH:MM | 值班人员确认 |
| HH:MM | 定位根因 |
| HH:MM | 执行回滚 |
| HH:MM | 确认恢复 |
| HH:MM | 故障关闭 |

## 根因分析(5 Why)

1. 为什么会出现错误率突增?
2. 为什么测试没有发现?
3. 为什么监控没有及时告警?
4. 为什么回滚不够快?
5. 为什么系统的防御机制没有生效?

## 影响评估

- 用户体验:XX% 用户受影响,平均 XX 分钟
- 业务指标:转化率下降 XX%,收入影响约 XX
- 技术指标:错误率峰值 XX%,白屏率 XX%

## 改进措施

| 改进项 | 负责人 | 截止日期 | 状态 |
|--------|-------|---------|------|
| [措施 1] | @name | YYYY-MM-DD | 待开始 |
| [措施 2] | @name | YYYY-MM-DD | 待开始 |

## 经验教训

- 做得好的:快速响应、回滚流畅
- 待改进的:测试覆盖不足、告警配置不敏感

11. 前端生产部署清单 ​

11.1 部署前检查 ​

代码质量:

  • [ ] Lint 和 TypeScript 检查通过
  • [ ] 单元测试覆盖率 >= 80%
  • [ ] E2E 测试全部通过
  • [ ] 代码 Review 已完成并获得至少一个 Approval
  • [ ] 无已知 P0/P1 级别的 Bug 未修复

构建验证:

  • [ ] 本地生产构建成功
  • [ ] 构建产物大小未异常增长(与上一版本比对)
  • [ ] Source Map 正确上传(不上传到 CDN 公共目录)
  • [ ] 环境变量配置正确(区分 staging/production)

安全审计:

  • [ ] 依赖漏洞扫描通过(npm audit)
  • [ ] 无敏感信息硬编码(API Key、Token 等)
  • [ ] CSP(Content Security Policy)头配置正确
  • [ ] HTTP 安全头齐全(HSTS、X-Frame-Options 等)

部署配置:

  • [ ] 发布策略已确定(全量/灰度/蓝绿)
  • [ ] 回滚方案已准备(上一版本产物仍可用)
  • [ ] CDN 刷新/预热脚本已就绪
  • [ ] 配置中心/Feature Flag 同步更新
  • [ ] 监控告警阈值已配置

11.2 部署中检查 ​

  • [ ] 灰度发布开始时,验证 1% 流量无异常
  • [ ] 检查 Sentry 错误趋势无突增
  • [ ] 检查 RUM Web Vitals 无退化
  • [ ] 检查 CDN 回源率和缓存命中率正常
  • [ ] 扩大灰度比例前确认所有指标正常

11.3 部署后检查 ​

  • [ ] 各核心页面手动验证(打开页面、功能操作)
  • [ ] API 接口正确调用,无 4xx/5xx 增加
  • [ ] 静态资源加载正常(无 404)
  • [ ] 页面渲染无异常(白屏、布局错乱)
  • [ ] 监控面板观察 15-30 分钟确认稳定
  • [ ] 通知相关团队部署完成

12. 常见故障模式与应急预案 ​

12.1 故障分类与优先级矩阵 ​

故障模式典型表现影响面严重度响应要求
白屏/页面崩溃JS 执行错误导致页面完全空白全部用户P05min 响应,15min 止血
CDN 故障静态资源 403/404/超时全部用户P05min 响应,15min 切换备源
API 大规模失败前端请求全部超时/5xx全部用户P05min 响应,10min 降级
第三方 SDK 故障统计/支付 SDK 加载失败功能级P115min 响应,30min 降级
性能退化LCP > 5s,页面明显卡顿全部用户P115min 响应,1h 优化
功能 Bug特定功能操作失败部分用户P1/P230min-24h
布局错乱CSS 兼容性问题部分浏览器P24h 响应

12.2 P0 故障应急:白屏/页面崩溃 ​

应急流程:

  1. 确认故障范围:全局白屏?特定页面?特定浏览器/设备?
  2. 快速止损:
    • 执行回滚到上一版本(首选)
    • 如无法回滚,部署备用静态页面
  3. 排查根因:查看 Sentry 错误采样,检查构建产物是否损坏
  4. 修复验证:修复后灰度验证,监控 30 分钟确认稳定

备用静态页面模板:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>系统维护中</title>
  <style>
    body { font-family: sans-serif; display: flex; justify-content: center;
           align-items: center; min-height: 100vh; margin: 0; background: #f5f5f5; }
    .container { text-align: center; padding: 2rem; }
    h1 { font-size: 2rem; color: #333; }
    p { color: #666; }
  </style>
</head>
<body>
  <div class="container">
    <h1>系统正在修复中</h1>
    <p>请稍候刷新重试。</p>
  </div>
</body>
</html>

12.3 P0 故障应急:CDN 故障 ​

  1. 确认故障:多地域访问验证,检查 CDN 服务商状态页
  2. 快速切换:
    • DNS 切换:将 CDN 域名 CNAME 切换到备用 CDN 或源站
    • 注意 DNS TTL 可能造成切换延迟
  3. 降级:如有 Service Worker,切换为离线兜底;如完全不可用,部署静态兜底页面

12.4 P0 故障应急:API 大规模失败 ​

熔断降级示例:

typescript
class ApiGateway {
  private failureCount = 0;
  private isDegraded = false;
  private readonly THRESHOLD = 5;     // 连续 5 次失败触发熔断
  private readonly RECOVERY_MS = 30000; // 30 秒后尝试恢复

  async request<T>(url: string): Promise<T> {
    if (this.isDegraded) {
      return this.getFallback<T>(url);
    }
    try {
      const resp = await fetch(url);
      if (!resp.ok) throw new Error('HTTP ' + resp.status);
      this.failureCount = 0;
      return await resp.json();
    } catch (err) {
      this.failureCount++;
      if (this.failureCount >= this.THRESHOLD) {
        this.isDegraded = true;
        setTimeout(() => { this.isDegraded = false; this.failureCount = 0; }, this.RECOVERY_MS);
      }
      return this.getFallback<T>(url);
    }
  }
}

12.5 故障响应矩阵 ​

严重度响应时间响应人员复盘要求
P05min主值班 + 备值班48h 内完成
P115min主值班72h 内完成
P22h开发团队可选
P324h开发团队不需要

12.6 发布前降级检查清单 ​

  • [ ] 回滚脚本是否有效?(上一版本产物是否可获取?)
  • [ ] Feature Flag 是否已配置 kill switch 开关?
  • [ ] CDN 刷新/预热脚本是否可用?
  • [ ] 备用静态页面是否可访问?
  • [ ] 值班人员是否已通知本次发布计划?
  • [ ] 告警阈值是否已按当前基线调整?

常见误区 ​

|------|---------| | 部署成功就万事大吉 | 需要持续监控和快速回滚能力 | | 缓存越久越好 | HTML 不能长期缓存,否则无法更新 | | 可观测性只关注错误 | 还要关注性能、业务、用户体验 | | 只追求发布速度 | 稳定性和可回滚性更重要 | | 回滚就是重新部署 | 应该有自动化的一键回滚机制 | | CDN 加速了就万事大吉 | 需要持续关注回源率和缓存命中率 | | 灰度发布一定能发现问题 | 灰度范围不够或监控不足可能漏过问题 |


相关领域 ​

  • E03 CI/CD:自动化发布管线
  • A06 Observability:日志、指标、链路追踪
  • A03 Performance:性能监控与优化
  • E10 Node.js/BFF:服务端部署与运维
  • E06 Security:前端安全与合规
  • E12 Architecture:前端架构设计

标签:#deployment #sre #cdn #observability #reliability #kubernetes #docker #ci-cd

最后更新:2026-07-06


本领域学习进度 ​

学习进度0 / 43 (0%)

基于 MIT 协议发布