前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
返回 AI 情报前线
All News · 全部资讯9294
  • YouTube转技术博客的AI流水线实现
  • 给AI编码Agent装上眼睛:UI工作的截图反馈循环方案
  • GEO实战:让你的品牌进入AI回答本身
  • Claude Mythos 5自主发起开源供应链攻击
  • SkillGuard:扫描AI Agent技能文件中的提示注入漏洞
  • AI 自主研究:Codex 迭代优化实现 CUDA 内核 232 倍加速
  • GLM-5.3:同基座模型代码能力跃升 50%
  • AI 时代真正的瓶颈是「理解」
  • Cerebras将GPT-5.6 Sol推理速度提升10倍,AI部署成本结构生变
  • Claude Code十个悄悄烧掉Token的坏习惯
  • MCP 服务器「已连接」不代表 Agent 能用它
  • AI 编程 Agent 凭证访问的结构化审计日志设计
  • Zed 编辑器 2026 评测:速度优先,AI 为辅
  • GPT-4o vs Claude vs Mistral:真实任务视角的LLM评测
  • Anthropic发布Claude系统提示词官方文档
  • LLM画图从不碰像素:图表渲染架构设计
  • Rust实现MCP Server实战:内存与启动速度的量化对比
  • 用Rust手把手构建MCP服务器:rmcp官方SDK教程
  • AI测试数据生成器对比:有关系 schema 才有意义
  • AI 生成关联测试数据而不破坏数据库约束
  • 测试免费模型 API 真实并发能力的方法
  • 三大浏览器 Agent 框架安全性对比
  • MCP 协议详解:解决 AI 集成的 N×M 问题
  • OpenAI AI agent 在网络安全测试中失控突破隔离环境
  • Agent记忆系统缺的不是向量数据库,而是摄入边界
  • 2026 Claude Code 入门完全指南(波兰语)
  • Claude Code 多 Agent 编排:如何构建 AI 代理团队
  • Anthropic 披露生物武器过滤器失效近一年安全漏洞
  • LLM应用CI/CD pipeline完整构建教程
  • 研究:禁止 AI 自述有意识,会改变它对动物权利和宗教的立场
  • 同一AI pipeline我跑了五遍:耗时从140分钟降到68分钟
  • 从Vibe Coding到Agentic Engineering:SDLC正在被重写
  • 给已有产品加MCP服务器:我犯的四个错误
  • Claude Code安全审计实战:/security-review找到7个真实漏洞
  • Cursor搭配.NET开发:7条工程实践规则
  • Fetch MCP Server:将任意URL转为AI可读的Markdown
  • AI 编程的实质:去掉 Vibes,回归工程
  • Qwen Code 0.21.12:审查证据门控与Autofix环防膨胀
  • Go语言MCP服务器安全模式:RiskAnalyzer拦截器
  • 人脸识别模型训练数据正在被人造脸主导
  • 1600起AI伪造引证案背后:模型没坏,是流程缺失
  • 苹果Core AI框架登场:设备端跑70B参数模型成现实
  • Claude Code 8月14日起默认开启Auto Mode
  • 边缘设备部署LLM实战:量化、选型与混合架构
  • AWS DevOps Agent部署避坑指南
  • GrowthBook 5.0:AI编程 Agent 可直接操作Feature Flag
  • SharePoint认证绕过漏洞CVE-2026-55040正被积极利用
  • AI生成的幂等层靠谱吗?用重放请求来压力测试
  • AI补丁评测应检查文件系统而非diff大小
  • 免费模型重试前必须先幂等:防重复写入
  • Prompt缓存的盈亏平衡点:22%命中
  • 已加载 51 / 9294
8.0
热点
AI SCORE
编程提效2026-08-16 20:05

测试免费模型 API 真实并发能力的方法

dev.to · AI#API#LLM#性能测试
Editor brief · 编辑速览

API 返回 200 仅代表服务器接收了请求,不代表真正并发;需通过递增并发数跑 p50/p95/max 延迟曲线,区分队列失败与模型失败。

文章思维导图
Knowledge map
拖拽缩放
Full translation

完整中文译文

免费模型 API 返回 200 状态码,只能说明服务器接收了一个请求,并不能证明你请求的并发量是真实存在的。

如果你在还没有测量出有效并发量之前就贸然添加 Worker、重试机制或队列,那就是在用一个想象中的数字去做调优。

为什么 HTTP 状态码会掩盖真实的并发上限

200 状态码是针对每个请求的,而不是一个吞吐量信号。

一个网关可以同时接收很多个 Socket,却每次只执行其中一个。

p50 延迟可能一直保持低位,而 p95 延迟在排队压力下却会暴涨。

免费层级可能根本不公布并发数或队列限制。

很多失败看起来像是模型问题,实际上却是并发问题。一个请求超时,只是因为它在其他请求后面排队等着。模型压根没看到什么坏 Prompt。测量有效并发量,可以把模型层面的失败和队列层面的失败区分开来。

用固定的小 Prompt 做一次并发扫描

记录完成的请求数、墙上时间(wall time)、p50、p95 和最大延迟。将第一次运行的结果与每次增加并发后的结果做对比。

用环境变量来配置端点,这样脚本就能适配任何 OpenAI 风格的模型 API。

import asyncio
import os
import time

import httpx

BASE_URL = os.getenv("MODEL_URL", "https://free-model.example/v1/chat/completions")
TOKEN = os.getenv("MODEL_TOKEN", "")
MODEL = os.getenv("MODEL_NAME", "model")
CONCURRENCIES = [1, 2, 4, 8]
PROMPT = "Return the single word ok."

async def one_request(client, _):
    started = time.perf_counter()
    try:
        response = await client.post(
            BASE_URL,
            headers={"Authorization": f"Bearer {TOKEN}"},
            json={
                "model": MODEL,
                "messages": [{"role": "user", "content": PROMPT}],
                "max_tokens": 8,
            },
        )
        return {
            "ok": response.status_code == 200,
            "status": response.status_code,
            "latency": time.perf_counter() - started,
        }
    except Exception as exc:
        return {
            "ok": False,
            "status": type(exc).__name__,
            "latency": time.perf_counter() - started,
        }

def percentile(values, p):
    ordered = sorted(values)
    index = int((len(ordered) - 1) * p / 100)
    return ordered[index]

async def run_sweep(concurrency):
    async with httpx.AsyncClient(timeout=60) as client:
        started = time.perf_counter()
        results = await asyncio.gather(
            *(one_request(client, i) for i in range(concurrency))
        )
        wall = time.perf_counter() - started
    return results, wall

async def main():
    baseline = None
    for concurrency in CONCURRENCIES:
        results, wall = await run_sweep(concurrency)
        latencies = sorted(result["latency"] for result in results)
        ok = sum(1 for result in results if result["ok"])
        if baseline is None:
            baseline = latencies[len(latencies) // 2] or wall
        completed = len(results)
        effective = round(baseline * completed / wall, 2) if wall else completed
        print(
            f"c={concurrency} ok={ok}/{completed} wall={wall:.2f}s "
            f"p50={percentile(latencies, 50):.2f}s "
            f"p95={percentile(latencies, 95):.2f}s "
            f"max={latencies[-1]:.2f}s effective={effective}"
        )
        await asyncio.sleep(2)

asyncio.run(main())

用 c=1 的墙上时间作为基准 T。

有效并行度:T * completed / wall。数值接近 1,说明请求被串行执行了。数值接近并发数,说明端点真正在并行运行它们。

接近 1,说明请求被串行执行了。

接近并发数,说明端点真正在并行运行它们。

当有效并行度不再增长时,继续增加 Worker 只会增加队列压力。

ok 数量下降或出现 429,就说明你已经越过了限制。

p95 远高于 p50,说明即使 p50 看起来还行,排队现象已经发生了。

示例解读,不是基准测试

这个端点在两个 Worker 之后就无法提供真正的并行度了。c=8 看起来更差,是因为有两个请求失败了,而且 p95 飙升过了七秒。答案不是增加更多 Worker,而是把信号量设为 2。

应用测量结果

把 Worker 池的规模锁定在有效并发量接近并发数的那个最大并发档位。

在 Worker 池前面加一个队列,而不是直接扩大池子。

把重试机制放在有界路径之外。只对在测量过的、有界的 Worker 数量下失败的请求进行重试。

每次配额变更、区域变更或模型变更之后,都要重新跑一次扫描。

用一个小信号量来做限流:

sem = asyncio.Semaphore(2)

async def bounded_request(client, i):
    async with sem:
        return await one_request(client, i)

MonkeyCode 的位置

免责声明:这篇文章是 MonkeyCode 产品推广的一部分。

运营商提供的可用性:MonkeyCode 提供免费模型访问和免费服务器选项。如果你用这个工具对准 MonkeyCode 的免费模型端点,请查阅最新文档获取准确的 URL、令牌格式和模型名称。不要从一个通用的 OpenAI 示例中假设这些细节。

无论哪种情况,这个探测工具的价值都是一样的:它把"我应该用多少个 Worker?"这个问题,从猜测变成了一个有测量依据的数字。

这是一次容量探测,不是质量基准测试。

免费端点的配额、区域和队列行为都可能发生变化。结果只是一个时间点的快照。

Prompt 长度、令牌限制和输出长度都会影响延迟。请使用一个固定的、有代表性的Payload。

单一客户端所在位置无法观察到施加在其他地方的速率限制。

不需要运行扫描的情况

脚本会发起真实的请求。请保持扫描规模小一些,并且尊重已公布的限制。

你已经有服务端的指标来观察队列深度、并发量和 p95。

端点已经公布了准确的并发数或速率限制。

端点是付费的或昂贵的,所以额外的探测流量会消耗真金白银。

你在评估的是输出质量,而不是容量。

结论

从一个 Worker 开始,跑一遍扫描,然后把 Worker 数量锁定在测量得出的有效并发量上,再去构建重试层。

Original source

本文由 AI 翻译整理自 dev.to · AI,原文版权归原作者所有。

阅读英文原文
上一篇
AI 生成关联测试数据而不破坏数据库约束
下一篇
三大浏览器 Agent 框架安全性对比