上一篇 下一篇 分享链接 返回 返回顶部

千人同时在线的 AI 浏览器,后端到底该怎么扛?

发布人:慈云数据-客服中心 发布时间:6小时前 阅读量:1

AI浏览器 高并发解决方案|附配置文件

随着大模型应用进入企业级落地阶段,“AI浏览器”正在成为一种新的智能入口。它不仅要像传统浏览器一样完成网页访问、账号登录、页面渲染、数据采集、自动化操作,还要叠加大模型推理、Agent任务编排、插件调用、网页理解、RPA自动执行等能力。

但当 AI 浏览器从单用户工具演进为多用户平台时,一个非常现实的问题就会出现:高并发如何支撑?

例如:

  • 同时有 1000 个用户打开 AI 浏览器会话;
  • 每个用户都在执行网页搜索、网页摘要、表单填写、数据采集;
  • 后端需要调度大量浏览器实例;
  • 浏览器实例会消耗 CPU、内存、网络和磁盘;
  • AI 推理又会带来额外的 Token、请求延迟和队列压力;
  • 页面自动化任务可能持续几十秒甚至数分钟。

如果没有合理的架构设计,系统很容易出现:

  • 浏览器实例爆满;
  • CPU 被 Chromium 进程打满;
  • 内存持续上涨直至 OOM;
  • WebSocket 连接断开;
  • 队列任务堆积;
  • AI 接口限流;
  • 用户等待时间过长;
  • 某个异常页面拖垮整个节点。

本文将从架构设计、任务调度、浏览器池、容器隔离、队列削峰、AI 接口限流、监控告警等角度,系统讲解 AI 浏览器的高并发解决方案,并附上可参考的配置文件。


一、AI浏览器高并发的核心难点

AI浏览器和传统Web服务不同,它的资源消耗更复杂。普通后端服务通常主要消耗 CPU、内存和数据库连接,而 AI 浏览器还要额外维护大量浏览器进程、页面上下文、WebSocket连接、自动化脚本以及AI模型调用链路。

1. 浏览器实例资源消耗高

以 Chromium 为例,一个无头浏览器实例通常会包含多个进程:

  • Browser 主进程;
  • Renderer 渲染进程;
  • GPU 进程;
  • Network Service 进程;
  • Extension 进程;
  • Crashpad 进程。

即使是 headless 模式,一个 Chromium 实例也可能消耗 150MB~500MB 内存。如果页面复杂、JS较多、图片较大,内存可能轻松超过 1GB。

如果不加限制地为每个请求启动一个新浏览器,高并发下服务器会迅速崩溃。

2. 页面任务时间长

AI浏览器任务通常不是瞬时完成的。比如:

  • 打开网页;
  • 等待页面加载;
  • 提取DOM结构;
  • 截图;
  • 调用大模型分析页面;
  • 执行点击、输入、滚动;
  • 再次等待页面响应;
  • 返回结果。

一个任务可能耗时 10 秒、30 秒甚至几分钟。任务越长,并发占用越严重。

3. AI接口存在限流

AI浏览器通常需要调用大模型接口,例如:

  • 页面摘要;
  • 网页问答;
  • 表格解析;
  • 指令规划;
  • DOM元素识别;
  • 多轮Agent决策。

大模型接口一般会有 TPM、RPM、并发连接数等限制。如果没有限流和队列机制,系统会频繁触发 429 错误。

4. 浏览器自动化存在不确定性

网页结构复杂且不可控,不同网站可能存在:

  • 页面加载慢;
  • 验证码;
  • 反爬机制;
  • 弹窗;
  • 登录态失效;
  • iframe嵌套;
  • JS长任务阻塞;
  • 第三方资源加载失败。

这意味着单个任务可能卡住,甚至导致浏览器实例异常。如果没有超时、熔断和隔离机制,异常任务会影响整个系统。


二、总体架构设计

一个稳定的 AI 浏览器高并发系统,建议采用分层架构:

用户端
  |
  | HTTP / WebSocket
  v
API Gateway 网关层
  |
  v
业务服务层
  |
  +--> 鉴权服务
  +--> 会话服务
  +--> 任务编排服务
  +--> AI调用服务
  |
  v
消息队列 / 任务队列
  |
  v
浏览器调度层
  |
  +--> Browser Pool
  +--> Page Context Pool
  +--> Worker Node
  |
  v
容器化浏览器集群
  |
  +--> Chromium / Playwright / Puppeteer
  |
  v
监控日志系统

推荐关键组件如下:

模块 推荐方案
API网关 Nginx / Kong / APISIX
后端服务 Node.js / Go / Python FastAPI
浏览器自动化 Playwright 优先,Puppeteer 次之
消息队列 Redis Stream / RabbitMQ / Kafka
任务队列 BullMQ / Celery / Temporal
缓存 Redis
数据库 PostgreSQL / MySQL
容器编排 Docker Compose / Kubernetes
监控 Prometheus + Grafana
日志 Loki / ELK
链路追踪 OpenTelemetry / Jaeger

三、高并发解决思路

AI浏览器高并发的核心原则是:不要让请求直接驱动浏览器实例,而是通过队列、池化、限流、隔离和弹性扩容来控制系统压力。

1. 浏览器实例池化

错误做法:

每来一个请求 -> 启动一个 Chromium -> 执行任务 -> 关闭 Chromium

这种方式会导致频繁启动浏览器,成本很高。Chromium启动过程本身就可能耗时数百毫秒到数秒,并且短时间大量启动会造成CPU峰值飙升。

推荐做法:

服务启动时预热N个浏览器实例
请求进入队列
Worker从浏览器池取可用实例
创建新的Browser Context执行任务
任务完成后释放Context
浏览器实例继续复用

Playwright 支持 Browser Context,它比完整浏览器实例更轻量,并且具备较好的隔离性。一个 Browser 可以承载多个 Context,但数量不能无限增加,需要根据机器配置控制。

推荐参数:

单台 8核16G 服务器:
Chromium实例数:4~8
每个Browser最大Context数:4~8
理论并发任务数:16~64

但实际要根据页面复杂度压测决定。


2. 队列削峰

高并发系统中最忌讳的是让所有请求同时打到浏览器执行层。正确做法是将任务放入队列,由Worker按系统承载能力消费。

队列的作用:

  • 削峰填谷;
  • 控制最大并发;
  • 支持失败重试;
  • 支持任务优先级;
  • 支持延迟任务;
  • 支持超时取消;
  • 支持任务状态查询。

例如用户提交一个 AI 浏览器任务后,接口立即返回任务ID:

{
  "taskId": "task_202501010001",
  "status": "queued"
}

前端可以通过轮询或 WebSocket 获取任务进度:

{
  "taskId": "task_202501010001",
  "status": "running",
  "progress": 65,
  "message": "正在分析网页内容"
}

这样可以避免HTTP请求长时间阻塞,也能提升系统稳定性。


3. 分级限流

AI浏览器至少需要三层限流:

用户级限流

防止单个用户滥用资源。

例如:

普通用户:最多同时执行2个浏览器任务
高级用户:最多同时执行10个浏览器任务
企业用户:按套餐配置

系统级限流

保护整体服务。

例如:

全局最大排队任务:10000
全局最大运行任务:500
单节点最大运行任务:50

AI模型限流

保护大模型接口不被打爆。

例如:

GPT类模型:每分钟最多500请求
Embedding模型:每分钟最多3000请求
视觉模型:每分钟最多100请求

限流可以使用令牌桶、漏桶或Redis计数器实现。


4. 浏览器任务隔离

高并发环境下,不建议所有任务共享一个浏览器上下文。正确方式是:

  • 不同用户使用不同 Context;
  • 敏感任务使用独立 Browser;
  • 高风险网站任务放入隔离节点;
  • 每个任务设置最大执行时间;
  • 每个Context任务结束后强制关闭;
  • 定期重启Browser进程防止内存泄漏。

推荐隔离策略:

任务类型 隔离级别
普通网页摘要 共享Browser,独立Context
登录态任务 独立Context,持久化UserData
支付/金融页面 独立Browser
高风险采集任务 独立容器
未知脚本页面 沙箱容器

5. 静态资源拦截

很多AI浏览器任务并不需要完整加载页面资源。例如网页摘要、DOM提取、文本采集等任务,不一定需要图片、字体、视频和广告脚本。

可以拦截以下资源:

  • image;
  • media;
  • font;
  • stylesheet;
  • analytics脚本;
  • 广告域名;
  • tracking请求。

这样可以显著降低带宽、CPU和内存消耗。

Playwright示例:

await page.route('**/*', async route => {
  const request = route.request();
  const type = request.resourceType();

  if (['image', 'media', 'font'].includes(type)) {
    return route.abort();
  }

  return route.continue();
});

对于需要截图、视觉理解的任务,可以关闭资源拦截或只拦截广告资源。


6. 超时与熔断

每个任务都必须配置超时,否则一个异常页面可能无限占用浏览器资源。

建议配置:

操作 超时时间
页面打开 15秒
DOM加载 10秒
页面完整加载 30秒
AI规划 20秒
单步点击/输入 5秒
总任务时间 120秒

如果连续出现异常,应触发熔断:

某个域名5分钟内失败率超过70%
暂停该域名任务3分钟
返回降级提示

熔断可以避免某个目标网站异常时拖垮系统。


四、浏览器池设计示例

下面是一个 Node.js + Playwright 的简化浏览器池设计。

const { chromium } = require('playwright');

class BrowserPool {
  constructor(options = {}) {
    this.maxBrowsers = options.maxBrowsers || 4;
    this.maxContextsPerBrowser = options.maxContextsPerBrowser || 6;
    this.browsers = [];
    this.index = 0;
  }

  async init() {
    for (let i = 0; i < this.maxBrowsers; i++) {
      const browser = await chromium.launch({
        headless: true,
        args: [
          '--no-sandbox',
          '--disable-dev-shm-usage',
          '--disable-gpu',
          '--disable-extensions',
          '--disable-background-networking',
          '--disable-default-apps',
          '--disable-sync'
        ]
      });

      this.browsers.push({
        browser,
        activeContexts: 0,
        createdAt: Date.now()
      });
    }
  }

  async acquireContext() {
    const available = this.browsers.find(
      item => item.activeContexts < this.maxContextsPerBrowser
    );

    if (!available) {
      throw new Error('NO_AVAILABLE_BROWSER_CONTEXT');
    }

    available.activeContexts++;

    const context = await available.browser.newContext({
      viewport: { width: 1365, height: 768 },
      userAgent:
        'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120 Safari/537.36'
    });

    const release = async () => {
      try {
        await context.close();
      } finally {
        available.activeContexts--;
      }
    };

    return { context, release };
  }

  async close() {
    for (const item of this.browsers) {
      await item.browser.close();
    }
  }
}

module.exports = BrowserPool;

这个示例仅适合演示,生产环境还需要增加:

  • 任务等待队列;
  • 浏览器健康检查;
  • 浏览器定期重启;
  • Context创建失败重试;
  • 资源占用统计;
  • Worker优雅退出;
  • 指标上报;
  • 崩溃恢复。

五、任务队列配置示例

如果使用 Node.js,可以采用 BullMQ + Redis 实现任务队列。

1. BullMQ队列配置

const { Queue } = require('bullmq');

const browserTaskQueue = new Queue('ai-browser-task', {
  connection: {
    host: process.env.REDIS_HOST || '127.0.0.1',
    port: Number(process.env.REDIS_PORT || 6379),
    password: process.env.REDIS_PASSWORD || undefined
  },
  defaultJobOptions: {
    attempts: 2,
    backoff: {
      type: 'exponential',
      delay: 3000
    },
    removeOnComplete: 1000,
    removeOnFail: 5000,
    timeout: 120000
  }
});

module.exports = browserTaskQueue;

2. Worker消费配置

const { Worker } = require('bullmq');
const BrowserPool = require('./browser-pool');

const pool = new BrowserPool({
  maxBrowsers: Number(process.env.MAX_BROWSERS || 4),
  maxContextsPerBrowser: Number(process.env.MAX_CONTEXTS_PER_BROWSER || 6)
});

async function runTask(job) {
  const { url, instruction } = job.data;

  const { context, release } = await pool.acquireContext();

  try {
    const page = await context.newPage();

    await page.route('**/*', async route => {
      const type = route.request().resourceType();
      if (['image', 'font', 'media'].includes(type)) {
        return route.abort();
      }
      return route.continue();
    });

    await page.goto(url, {
      waitUntil: 'domcontentloaded',
      timeout: 15000
    });

    const title = await page.title();
    const content = await page.locator('body').innerText({ timeout: 10000 });

    // 此处可接入AI模型进行摘要、问答、指令规划
    return {
      title,
      instruction,
      content: content.slice(0, 5000)
    };
  } finally {
    await release();
  }
}

async function start() {
  await pool.init();

  const worker = new Worker(
    'ai-browser-task',
    async job => {
      return await runTask(job);
    },
    {
      connection: {
        host: process.env.REDIS_HOST || '127.0.0.1',
        port: Number(process.env.REDIS_PORT || 6379),
        password: process.env.REDIS_PASSWORD || undefined
      },
      concurrency: Number(process.env.WORKER_CONCURRENCY || 16),
      lockDuration: 180000
    }
  );

  worker.on('completed', job => {
    console.log(`Job ${job.id} completed`);
  });

  worker.on('failed', (job, err) => {
    console.error(`Job ${job?.id} failed`, err);
  });
}

start();

这里需要注意:WORKER_CONCURRENCY 不应大于浏览器池可承载的最大 Context 数。比如:

MAX_BROWSERS=4
MAX_CONTEXTS_PER_BROWSER=6
最大Context容量 = 24
WORKER_CONCURRENCY 建议设置为 16~20

保留一定冗余有利于系统稳定。


六、Nginx网关配置文件

AI浏览器通常会使用 WebSocket 推送任务进度,因此 Nginx 必须正确配置 WebSocket 转发、超时时间和上传限制。

下面是一个参考配置:

upstream ai_browser_api {
    least_conn;
    server api-1:3000 max_fails=3 fail_timeout=30s;
    server api-2:3000 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name ai-browser.example.com;

    client_max_body_size 20m;

    location / {
        proxy_pass http://ai_browser_api;
        proxy_http_version 1.1;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 10s;
        proxy_send_timeout 120s;
        proxy_read_timeout 120s;
    }

    location /ws/ {
        proxy_pass http://ai_browser_api;
        proxy_http_version 1.1;

        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
}

如果AI浏览器任务较长,建议不要让HTTP接口一直等待任务结果,而是通过任务ID + WebSocket/轮询返回进度。


七、Docker Compose配置文件

下面给出一个适合中小规模部署的 Docker Compose 示例,包括 API、Worker、Redis、Prometheus 和 Grafana。

version: "3.9"

services:
  redis:
    image: redis:7-alpine
    container_name: ai-browser-redis
    command: redis-server --appendonly yes --maxmemory 1gb --maxmemory-policy allkeys-lru
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    restart: always

  api:
    image: node:20-bullseye
    container_name: ai-browser-api
    working_dir: /app
    command: sh -c "npm install && npm run start"
    volumes:
      - ./app:/app
    ports:
      - "3000:3000"
    environment:
      NODE_ENV: production
      REDIS_HOST: redis
      REDIS_PORT: 6379
      API_PORT: 3000
      MAX_PENDING_TASKS: 10000
    depends_on:
      - redis
    restart: always

  worker:
    image: mcr.microsoft.com/playwright:v1.42.1-jammy
    container_name: ai-browser-worker
    working_dir: /app
    command: sh -c "npm install && node worker.js"
    volumes:
      - ./app:/app
    environment:
      NODE_ENV: production
      REDIS_HOST: redis
      REDIS_PORT: 6379
      MAX_BROWSERS: 4
      MAX_CONTEXTS_PER_BROWSER: 6
      WORKER_CONCURRENCY: 16
      BROWSER_TASK_TIMEOUT: 120000
    shm_size: "2gb"
    deploy:
      resources:
        limits:
          cpus: "4"
          memory: 8G
        reservations:
          cpus: "2"
          memory: 4G
    depends_on:
      - redis
    restart: always

  prometheus:
    image: prom/prometheus:latest
    container_name: ai-browser-prometheus
    volumes:
      - ./deploy/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"
    restart: always

  grafana:
    image: grafana/grafana:latest
    container_name: ai-browser-grafana
    ports:
      - "3001:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    restart: always

volumes:
  redis-data:
  grafana-data:

重点说明:

shm_size: "2gb"

Chromium 在 Docker 中运行时非常依赖 /dev/shm。如果不设置,默认共享内存可能过小,容易导致页面崩溃或浏览器异常退出。


八、Kubernetes部署配置示例

当并发规模继续上升,例如达到几百到几千个浏览器任务并发,建议迁移到 Kubernetes。

下面是 Worker 的 Deployment 示例:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ai-browser-worker
  labels:
    app: ai-browser-worker
spec:
  replicas: 5
  selector:
    matchLabels:
      app: ai-browser-worker
  template:
    metadata:
      labels:
        app: ai-browser-worker
    spec:
      containers:
        - name: worker
          image: your-registry/ai-browser-worker:latest
          imagePullPolicy: Always
          env:
            - name: REDIS_HOST
              value: "redis.default.svc.cluster.local"
            - name: REDIS_PORT
              value: "6379"
            - name: MAX_BROWSERS
              value: "4"
            - name: MAX_CONTEXTS_PER_BROWSER
              value: "6"
            - name: WORKER_CONCURRENCY
              value: "16"
            - name: BROWSER_TASK_TIMEOUT
              value: "120000"
          resources:
            requests:
              cpu: "2"
              memory: "4Gi"
            limits:
              cpu: "4"
              memory: "8Gi"
          volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sh", "-c", "sleep 20"]
      volumes:
        - name: dshm
          emptyDir:
            medium: Memory
            sizeLimit: 2Gi
      terminationGracePeriodSeconds: 60

如果每个 Worker 最大并发为 16,副本数为 5,则理论并发为:

16 × 5 = 80

实际生产中建议保守估算,比如按 60~70% 计算稳定并发容量。


九、HPA自动扩容配置

Kubernetes 中可以根据 CPU、内存或自定义指标扩容。对于 AI浏览器场景,最推荐使用“队列长度”作为扩容指标。

如果暂时没有接入自定义指标,可以先使用 CPU 扩容:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: ai-browser-worker-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: ai-browser-worker
  minReplicas: 3
  maxReplicas: 30
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 65

更理想的扩容策略:

队列等待任务数 > 100,扩容
队列等待时间 P95 > 30秒,扩容
CPU使用率 > 70%,扩容
内存使用率 > 75%,扩容
AI接口429错误率上升,不盲目扩容,而是限流

需要注意,扩容浏览器 Worker 并不能解决所有问题。如果瓶颈在 AI 模型限流或目标网站响应慢,盲目增加 Worker 反而会放大失败率。


十、AI模型调用限流配置

AI浏览器的任务经常要多次调用模型。例如一个网页自动化任务可能包含:

  1. 根据用户指令生成执行计划;
  2. 分析页面DOM;
  3. 判断下一步点击哪个按钮;
  4. 总结页面结果;
  5. 生成最终回答。

如果并发任务很多,模型接口会成为关键瓶颈。因此需要单独做模型调用网关。

一个简单的限流配置可以这样设计:

aiModels:
  default:
    provider: openai-compatible
    baseUrl: https://api.example.com/v1
    timeoutMs: 30000
    retry:
      maxAttempts: 2
      backoffMs: 1000

  limits:
    chat:
      rpm: 500
      tpm: 300000
      maxConcurrent: 50

    vision:
      rpm: 100
      tpm: 100000
      maxConcurrent: 10

    embedding:
      rpm: 3000
      maxConcurrent: 100

模型调用层建议具备以下能力:

  • API Key池;
  • 多模型路由;
  • 自动降级;
  • Token预算;
  • 请求缓存;
  • 失败重试;
  • 超时控制;
  • 429退避;
  • 调用日志审计。

十一、环境变量配置文件

下面是一个 .env.production 示例:

NODE_ENV=production

API_PORT=3000

REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=

MAX_PENDING_TASKS=10000
MAX_RUNNING_TASKS=500

MAX_BROWSERS=4
MAX_CONTEXTS_PER_BROWSER=6
WORKER_CONCURRENCY=16

BROWSER_HEADLESS=true
BROWSER_TASK_TIMEOUT=120000
PAGE_GOTO_TIMEOUT=15000
PAGE_ACTION_TIMEOUT=5000

BLOCK_IMAGE=true
BLOCK_MEDIA=true
BLOCK_FONT=true
BLOCK_ADS=true

AI_BASE_URL=https://api.example.com/v1
AI_API_KEY=replace_with_your_key
AI_MODEL=gpt-4o-mini
AI_TIMEOUT=30000
AI_MAX_CONCURRENT=50
AI_RPM_LIMIT=500

LOG_LEVEL=info
METRICS_PORT=9100

生产环境中不建议将密钥直接写入 .env 文件,应使用:

  • Kubernetes Secret;
  • Docker Secret;
  • Vault;
  • 云厂商密钥管理服务。

十二、Prometheus监控配置

AI浏览器系统必须做监控,否则无法判断瓶颈在哪里。

建议监控以下指标:

指标 说明
queue_waiting_jobs 队列等待任务数
queue_active_jobs 正在执行任务数
task_success_total 成功任务数
task_failed_total 失败任务数
task_duration_p95 任务P95耗时
browser_active_contexts 活跃Context数量
browser_crash_total 浏览器崩溃次数
node_cpu_usage 节点CPU使用率
node_memory_usage 节点内存使用率
ai_request_total AI请求总数
ai_429_total AI限流次数
ai_latency_p95 AI调用P95延迟

Prometheus配置示例:

global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "ai-browser-api"
    static_configs:
      - targets: ["api:9100"]

  - job_name: "ai-browser-worker"
    static_configs:
      - targets: ["worker:9100"]

  - job_name: "redis"
    static_configs:
      - targets: ["redis-exporter:9121"]

告警规则示例:

groups:
  - name: ai-browser-alerts
    rules:
      - alert: HighQueueBacklog
        expr: queue_waiting_jobs > 1000
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "AI浏览器任务队列积压严重"
          description: "等待任务数超过1000,持续5分钟"

      - alert: BrowserCrashTooMany
        expr: increase(browser_crash_total[5m]) > 10
        for: 2m
        labels:
          severity: critical
        annotations:
          summary: "浏览器崩溃次数过多"
          description: "5分钟内浏览器崩溃超过10次"

      - alert: AIModelRateLimited
        expr: increase(ai_429_total[5m]) > 20
        for: 2m
        labels:
          severity: warning
        annotations:
          summary: "AI模型接口触发限流"
          description: "5分钟内AI接口429错误超过20次"

十三、性能压测建议

上线前必须压测。AI浏览器压测不能只看QPS,还要关注任务完成率和资源曲线。

建议压测维度:

  1. 并发任务数:10、50、100、300、500逐步增加;
  2. 任务类型:网页摘要、截图、自动点击、登录态任务;
  3. 页面复杂度:静态页面、SPA页面、重资源页面;
  4. AI调用次数:无AI、1次AI、多轮AI;
  5. 任务时长:短任务、中任务、长任务;
  6. 异常页面比例:模拟10%超时页面;
  7. 模型限流场景:模拟429和网络错误。

核心观察指标:

任务成功率 >= 99%
P95任务耗时可接受
CPU长期低于75%
内存无持续泄漏
浏览器崩溃率低
队列等待时间可控
AI接口错误率可控

如果压测发现内存持续上涨,需要检查:

  • Context是否关闭;
  • Page是否关闭;
  • 下载文件是否清理;
  • 截图缓存是否释放;
  • 是否存在全局变量持有页面对象;
  • Browser是否定期重启。

十四、生产最佳实践

1. Worker定期重启

浏览器进程长时间运行后可能出现内存碎片或泄漏,建议定期重启:

每个Browser执行500个任务后重启
或每运行2小时重启
或内存超过阈值重启

2. 任务分级队列

不同任务消耗不同,建议拆分队列:

light-task:网页文本提取、摘要
normal-task:自动点击、表单填写
heavy-task:截图、视觉识别、长流程Agent
isolated-task:高风险网站、登录态任务

不同队列配置不同并发,避免重任务阻塞轻任务。

3. 登录态单独管理

对于需要账号登录的网站,不建议在任务结束后简单销毁所有状态。可以使用加密存储的 storageState:

await context.storageState({ path: 'state/user-123.json' });

但必须注意:

  • 用户隔离;
  • 文件加密;
  • 定期失效;
  • 权限控制;
  • 审计日志。

4. 降级策略

当系统压力过高时,可以降级:

  • 只返回文本摘要,不截图;
  • 减少AI多轮规划次数;
  • 禁止重任务进入;
  • 暂停低优先级用户;
  • 使用缓存结果;
  • 延迟执行批量任务。

5. 安全策略

AI浏览器可能访问外部网页,必须注意安全:

  • 禁止访问内网地址;
  • 防止 SSRF;
  • 限制下载文件类型;
  • 禁止执行本地命令;
  • 容器只读文件系统;
  • 限制网络出口;
  • 对用户输入进行审计;
  • 浏览器运行在非root用户下。

十五、推荐容量规划

假设单个 Worker 节点配置为:

CPU:4核
内存:8GB
MAX_BROWSERS=4
MAX_CONTEXTS_PER_BROWSER=6
WORKER_CONCURRENCY=16

保守估算:

单节点稳定并发:12~16个任务
10个节点稳定并发:120~160个任务
30个节点稳定并发:360~480个任务

如果任务较轻,例如只做DOM提取和文本摘要,单节点可以更高;如果任务包含截图、视觉模型、复杂SPA页面,单节点并发应降低。

容量规划公式可以简化为:

稳定并发 = Worker节点数 × 单节点Worker并发 × 稳定系数

其中稳定系数建议取:

轻任务:0.8
普通任务:0.6
重任务:0.4

结语

AI浏览器的高并发本质上不是简单地“多开几个浏览器”,而是一套完整的工程体系。它需要在浏览器池、任务队列、资源隔离、AI限流、容器调度、监控告警、安全控制之间取得平衡。

一个可靠的生产级方案应当具备以下能力:

  • 浏览器实例池化;
  • Context级别隔离;
  • 任务队列削峰;
  • 用户级、系统级、模型级限流;
  • 超时、重试、熔断;
  • Docker/Kubernetes容器化部署;
  • Prometheus监控与告警;
  • 基于队列长度的自动扩容;
  • 清晰的降级策略;
  • 严格的安全边界。

如果是中小规模业务,可以先使用 Docker Compose + Redis + BullMQ + Playwright 搭建基础版本;如果并发规模提升到数百甚至上千,则建议迁移到 Kubernetes,并引入 HPA、任务分级队列、独立模型网关和更完善的监控体系。

真正稳定的 AI 浏览器系统,不是追求单机极限并发,而是追求可控、可观测、可扩展、可恢复。只要架构设计合理,即使面对复杂网页、大量用户和多轮AI调用,也能保持系统稳定运行。

目录结构
全文