Firecrawl 负载压测实录:Fly.io 自动扩缩容与并发软硬限制调优(Test 3) 网页爬虫后端AI 应用【免费下载链接】firecrawlThe web data API to search, scrape, and interact at scale. 项目地址https://gitcode.com/GitHub_Trending/fi/firecrawl点击查看免费下载导读本文基于 Firecrawl 仓库 load-test-results/tests-1-5 中的第三次抓取Scraping负载压测报告完整还原一次真实的生产级容量验证过程在 Fly.io 上启用自动扩缩容、通过http_service.concurrency软硬并发限制约束流量并使用 Artillery 以四段式加压脚本对/scrape接口发起 9000 次请求。读完本文你将掌握 Fly.io 并发限制hard_limit / soft_limit的含义与调优思路、Artillery 分段压测脚本的编写方式以及如何从 CPU、内存、并发与响应时间指标中定位扩容瓶颈并制定下一轮实验方案。背景这是一系列迭代式压测的第三轮这份报告位于 apps/test-suite/load-test-results/tests-1-5是整个tests-1-5目录中五轮压测的一部分。它与同目录下的 load-test-2.md、load-test-4.md 共同构成一条清晰的调优主线轮次核心改动失败率平均响应时间Test #2无扩缩容2 台机器跑满61.6%5473 超时3682.1 msTest #3本文启用 Fly.io 自动扩缩容soft75 / hard1007.3%653 超时 2 个 5023037.2 msTest #4调整为 soft50 / hard10014.8%1329 超时无 5023547.9 msTest #5Artillery timeout 调至 30s0.04%仅 4 个 5025661.8 ms可以看到Test #3 是「从完全不扩缩容 → 引入自动扩缩容」的关键转折点把失败率从 61.6% 压到 7.3%代价是通过扩容承接了负载但延迟指标仍不理想。这也是本文作为独立报告最重要的价值所在。测试环境5 台机器的 Fly.io 集群拓扑本次压测的目标环境是部署在 Fly.io 上的 staging 服务fly.staging.toml对应配置目标地址为 staging 环境的 Fly 应用。压测时集群共配置 5 台机器规格统一为performance-cpu-1x2048MBMachineSize/CPUStatuse286de4f711e86 mia (app)performance-cpu-1x2048MBalways on73d8dd909c1189 mia (app)performance-cpu-1x2048MBalways on6e82050c726358 mia (app)performance-cpu-1x2048MBpaused4d89505a6e5038 mia (app)performance-cpu-1x2048MBpaused48ed6e6b74e378 mia (app)performance-cpu-1x2048MBpaused这里有一个关键设计只有 2 台机器常驻always on另外 3 台处于 paused 状态作为自动扩缩容的弹性资源池。压测开始后Fly.io 的 autoscaling 会根据负载自动拉起scale up暂停的机器来分担流量——这正是 Test #3 与 Test #2只有 2 台常驻、无弹性的本质区别。从 Fly.io 的部署模型看mia表示机器所在的地域Miami 节点(app)表示它承载的是主应用。这种「常驻 弹性」的混合拓扑非常适合抓取类 API低峰期只保留少量实例节省成本高峰期靠自动扩缩容吸收突发流量。压测配置Fly.io 并发限制 Artillery 四段式加压Fly.io 侧http_service.concurrency 软硬限制本次测试在fly.staging.toml中为 HTTP 服务配置了基于请求数requests的并发控制# fly.staging.toml [http_service.concurrency] type requests hard_limit 100 soft_limit 75这两个参数是 Fly.io 负载均衡与扩容决策的核心type requests以「当前在途请求数」作为并发度量口径而非连接数或 CPUhard_limit硬限制单台机器在途请求数的绝对上限这里是 100。超过后Fly Proxy 会将新请求路由到其他机器如果没有可用机器请求会排队或返回错误soft_limit软限制扩容触发阈值这里是 75。当机器上的在途请求数持续超过 soft_limit 时Fly.io 会判定实例过载触发自动扩容拉起更多机器。对照仓库源码可以印证这一设计在应用层的落地API 服务在 apps/api/src/lib/concurrency-limit.ts 中实现了团队级的并发限制getEffectiveConcurrencyLimit、Redis 队列concurrency-limit-queue:前缀的 key以及受限任务的入队/清理逻辑pushConcurrencyLimitedJob、cleanOldConcurrencyLimitEntries等。也就是说除了 Fly 网关层的硬/软限制应用自身还有一层基于 Redis 的并发闸门两者共同防止抓取任务把后端打垮。Artillery 侧四段式加压脚本负载由 Artillery 生成采用「起步 → 加压 → 峰值 → 冷却」的经典四阶段模式总时长 7 分钟# load-test.yml - duration: 60 arrivalRate: 10 # Initial load - duration: 120 arrivalRate: 20 # Increased load - duration: 180 arrivalRate: 30 # Peak load - duration: 60 arrivalRate: 10 # Cool down每个 phase 的含义阶段时长arrivalRate说明160s10 req/s初始负载验证服务基线2120s20 req/s加压触发扩缩容决策3180s30 req/s峰值负载考验弹性上限460s10 req/s冷却观察资源回落arrivalRate表示每秒钟新创建的虚拟用户vuser数量而不是瞬时并发量实际并发取决于请求耗时——请求越慢同一时刻在途的请求越多对 soft/hard limit 的压力就越大。仓库中的实际压测脚本 apps/test-suite/load-test.yml 展示了完整的 Artillery 工程化写法config中通过target指向 staging 环境、http.timeout设置请求超时压测后期调整到了 30s、defaults.headers注入Authorization: Bearerscenarios里定义了 Crawl a URL 这类多步场景先POST /crawl拿jobId再用until/retry轮询/crawl/status。Test #3 报告中的 Scrape 场景即对应脚本中注释掉的POST /scrape流程请求体携带url、pageOptions.onlyMainContent等抓取参数。运行方式在 apps/test-suite 目录下执行npm install -g artillery后用artillery run load-test.yml即可复现同类压测详见 apps/test-suite/README.md。结果9000 次请求下的完整指标压测于14:53:32(-0300)结束以下为 Artillery 报告全量指标MetricValueerrors.ETIMEDOUT653errors.Failed capture or match2http.codes.2008345http.codes.5022http.downloaded_bytes0http.request_rate11/sechttp.requests9000http.response_time.min979http.response_time.max9941http.response_time.mean3037.2http.response_time.median2059.5http.response_time.p957709.8http.response_time.p999416.8http.responses8347vusers.completed8345vusers.created9000vusers.created_by_name.Scrape a URL9000vusers.failed655vusers.session_length.min1044.5vusers.session_length.max9998.8vusers.session_length.mean3109.7vusers.session_length.median2143.5vusers.session_length.p957709.8vusers.session_length.p999416.8指标解读成功率与错误分布9000 个虚拟用户中完成 8345 个vusers.completed失败 655 个失败率约 7.3%。失败几乎全部来自errors.ETIMEDOUT653 个另有 2 个Failed capture or match断言/提取失败与 2 个 HTTP 502网关错误占比 0.02%。ETIMEDOUT 占绝对主导说明问题出在「请求发出后等待响应超时」而不是鉴权对比 Test #2 出现过 401/402或断言不匹配。响应时间平均 3037.2 ms、中位数 2059.5 ms——中位数远低于均值说明多数请求较快长尾由峰值阶段拖累p95 达 7709.8 msp99 达 9416.8 ms峰值 9941 ms。结合 Test #5 的经验可以推断Artillery 默认超时30s 配置前的默认值偏紧在扩容尚未完成的窗口期慢请求容易被判定为 ETIMEDOUT。吞吐http.request_rate为 11/sec这是整个测试期间的平均到达速率而阶段 3 的到达率是 30 req/s中间的差距正反映了峰值阶段大量请求积压/超时。会话时长vusers.session_length的中位数 2143.5 ms 与响应时间中位数基本吻合p99 9416.8 ms 与响应时间 p99 一致说明「会话耗时 ≈ 等待响应耗时」没有额外的排队拖累。监控面板扩容确实发生了压测期间采集的资源指标见下图从这份四联面板可以读到与报告结论互相印证的信息左上Memory Utilization总内存稳定在约 1.8 GiB各实例曲线平缓无内存泄漏迹象内存不是本次瓶颈右上CPU Utilization14:46 左右开始攀升14:4814:50 触及约 95% 的高位随后回落——CPU 在峰值阶段被充分压榨左下App Concurrency峰值阶段在途并发接近 100正好逼近hard_limit 100的闸口说明压测成功打满了配置上限右下5min Load Avg14:47 后负载上升14:51 达到约 70% 峰值趋势与 CPU、并发完全同步。三个暂停实例被自动拉起scaling up正是「并发触达 soft_limit → Fly 扩容」的直接证据没有自动扩缩容的 Test #2 两台机器 CPU 双双 100%、失败率 61.6%而 Test #3 扩容后 CPU 峰值被抑制在约 95%失败率骤降至 7.3%。结论扩容有效但阈值仍需校准报告给出了三条明确结论性能系统承接了 9000 次请求平均响应时间 3037.2 ms但仍有 653 个超时和 2 个 502自动扩缩容测试中自动扩容了 3 台机器但扩容速度/时机不足以完全消除错误——扩容动作发生在负载高峰期间存在一段「负载已升、实例未就绪」的窗口超时集中于此响应时间峰值响应时间 9941 ms说明系统在峰值负载下明显吃力延迟长尾需要进一步压缩。结合源码看抓取链路本身是重活Firecrawl 的 Scrape 流程在 apps/api/src/scraper/scrapeURL 中涉及页面下载、HTML 解析与 Markdown 转换等多步处理仓库还为此维护了独立的 Rust 原生实现与 go-html-to-md 转换服务单请求耗时长、CPU 密集因此在到达率不高平均 11 req/s的情况下仍能把 CPU 打到 95%——这解释了为什么扩容是比提升单机吞吐更有效的杠杆。下一步软硬限制的再校准报告针对发现的问题提出了下一轮实验方案调整软限制将soft_limit改为 100、hard_limit改为 50验证「机器更快启动、减少 502」的假设继续压测用新配置跑相同脚本对比失败率与延迟是否有改善。这个调优方向背后是 Fly.io 扩缩容的一个微妙权衡soft_limit越低扩容越敏感、越早拉起新机器但也会导致实例频繁伸缩、资源利用率下降而hard_limit是单机在途请求的上限设得太低可能让请求更早溢出到未就绪的机器上反而抬高错误率。Test #3soft75/hard100与 Test #4soft50/hard100的结果差异7.3% vs 14.8% 失败率说明阈值组合对失败率的影响是显著且非单调的必须靠多轮实测来收敛。报告中「将 soft 提到 100、hard 降到 50」看似反直觉实则是在尝试另一种策略让单机尽量多扛soft 高 → 不易触发扩容同时用更低的 hard 把流量尽快分流到弹性实例避免在途请求长时间堵在单机上形成 ETIMEDOUT 长尾。后续轮次Test #5则转向调整 Artillery 的http.timeout到 30s把「系统真实响应能力」和「客户端耐心」解耦最终把失败率压到 0.04%从侧面印证了 Test #3 中大量 ETIMEDOUT 与客户端超时阈值偏紧直接相关。结语把「容量验证」变成可复用的工程方法Test #3 这份报告的价值在于它展示了一套完整的容量验证闭环用四段式 Artillery 脚本制造可控负载 → 通过 Fly.io 软硬并发限制控制扩容行为 → 用资源监控面板确认扩容真实发生 → 用响应时间分布定位失败根因 → 基于数据提出下一轮配置假设。同目录下连续的 load-test-2.md、load-test-4.md、load-test-5.md 记录了后续迭代可作为完整的调优案例对照阅读而 apps/test-suite/load-test.yml 与 apps/api/src/lib/concurrency-limit.ts 则是从「压测脚本」与「应用层并发闸门」两个角度深入这套体系的入口。赞分享网页爬虫后端AI 应用【免费下载链接】firecrawlThe web data API to search, scrape, and interact at scale. 项目地址https://gitcode.com/GitHub_Trending/fi/firecrawl点击查看免费下载相关推荐Firecrawl 负载测试实战用 Artillery 压测 Scrape 接口与 Fly.io 性能调优Firecrawl 负载测试实战用 Artillery 压测 Scrape 接口与 Fly.io 性能调优 本指南以 Firecrawl 开源仓库中 load网页爬虫后端AI 应用Llama 3自动扩缩容基于负载的动态资源调整Llama 3自动扩缩容基于负载的动态资源调整 引言大模型推理的资源管理挑战 在大规模语言模型Large Language Model, LLM部署过程人工智能大模型基础模型本地部署kvcached与vLLM集成实战无缝提升多模型服务性能kvcached与vLLM集成实战无缝提升多模型服务性能 在当今AI大模型应用日益普及的背景下高效管理GPU资源、提升多模型服务性能成为开发者面临的重要挑战人工智能大模型模型推理服务内存管理模型优化上一篇快速掌握VectorDBPython向量数据库的完整入门指南下一篇pi-gpio核心API解析open、read、write函数使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考