ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

如何解决大模型网关超时?从Cloudflare 100秒限制到OCI负载均衡器迁移实践

如何解决大模型网关超时?从Cloudflare 100秒限制到OCI负载均衡器迁移实践 上个月我被一个大模型网关的超时问题折腾到凌晨两点。服务的结构其实很简单一台带GPU的服务器部署了兼容OpenAI接口的推理服务前面套了一层域名入口方便用户通过统一的API地址访问。反馈也很明确只要请求处理超过一分半客户端就掉线报错要么是“连接重置”要么是“响应超时”。我一层层往下查后端日志里请求明明成功了进程也没有异常最后才意识到问题根本不在我的程序上而是站在域名边缘的那个转发层。这个转发层就是不少人默认在用的Cloudflare而它对大模型网关有一个非常出名的限制源站响应等待上限100秒常用可用端口也被锁死在80/443。这篇文章就是那次排障过程的完整复盘。我会从域名、端口、超时三个角度拆开讲为什么Cloudflare这套链路对大模型网关来说处处别扭为什么最终换到OCI免费L7云负载均衡器以后问题彻底消失以及换网关过程中要避开哪几个隐形坑。文章适合两类读者一类是自建大模型API服务、正琢磨怎么把入口层从缓存型边缘服务换成更适合长耗时接口的开发者和运维朋友另一类是已经踩了超时坑但还没定位到问题根源的人。1. 大模型网关的“入口”为什么比业务代码更容易踩坑1.1 网关入口的三层博弈域名、端口、转发大模型网关和普通网站有个非常不一样的地方它不是一个“给人看”的页面而是一个“给程序调用”的API端点。普通网站慢一点、缓存一下用户还能忍受API网关一旦出现连接断开、响应超时客户端会直接报错如果下游没有做好重试退避还容易把源站打挂。一个自建模型网关对外提供服务至少要打通三层域名层决定客户端用什么地址访问涉及DNS解析、TLS证书、可能的区域就近接入端口层决定流量进入源站时走哪个TCP端口以及公网到源站之间的映射关系转发层决定域名和端口之间的连接是否被中间设备接管、改写甚至主动掐断。很多人第一反应是“用Cloudflare”因为免费、配置快、自带证书。但对大模型网关来说Cloudflare恰恰是这三层里最容易出问题的一层。它不是不好而是它的产品定位是给“以毫秒为单位的网页流量”设计的不是给“以分钟为单位的长时推理流量”设计的。1.2 端口折中方案看着能用实际处处别扭先说端口。Cloudflare的反向接入层在前面免费层基本只放行80/443。如果你的模型服务监听的是8080、18080、9000这种端口要么改端口要么在Cloudflare里折腾各种转发规则把流量引进去——但不管哪条路本质上都是在“迁就边缘设备的限制”而不是按需设计架构。我见过不少项目被端口问题逼得做各种折中把多个服务塞到同一个443端口下用路径来区分 /v1/chat、/v2/embedding、/admin。表面看能跑但很快会遇到几个问题路径路由规则越堆越多改一处路由就要重新发布网关配置某些服务依赖独立端口做回调、健康检查或debug接口路径方案覆盖不了证书统一挂在443下多域名、多证书场景切换时非常别扭。不是说这种方案一定不行而是它把“架构问题”转化成了“规则管理问题”长期维护成本很高。真正的大模型网关往往同时要接SSE流式输出、WebSocket语音、普通REST推理理想状态是每个服务都能自由选择端口和路径而不是被入口层卡住。1.3 三层问题的交叉点超时才是真正的导火索如果说端口问题只是添堵超时问题就是引爆点。Cloudflare对HTTP请求有一个硬限制从请求到达边缘节点到源站返回响应等待上限是100秒。这个限制在普通网站上几乎无感因为绝大多数页面请求3秒内就完事了但大模型推理恰恰相反一个稍微复杂一点的生成任务动辄几十秒碰上长上下文模型100秒根本不够用。所以最后走向OCI免费L7负载均衡器不是“为了换而换”而是因为域名、端口、超时这三个问题只有L7负载均衡器能同时解开。它不做缓存不抢端口空闲超时还可以自己调正好补上了大模型网关最缺的那块拼图。2. Cloudflare 100秒超时对大模型网关的“精准打击”2.1 限制到底卡在哪一个环节先说清楚这个100秒限制的准确含义。客户端发出的HTTPS请求会先到Cloudflare边缘节点边缘节点再与你的源站建立连接。Cloudflare默认等待源站“完成响应”的最长时间是100秒。如果一个POST请求发到你的推理服务模型算了110秒才返回结果那么在100秒时Cloudflare就已经判定这次请求超时给客户端回一个错误响应同时切断和源站的连接。源站那边可能还在继续算算完发现连接已经被拔了这就是典型的“源站日志显示成功、客户端却报错”的场景。再补充一个容易被忽略的点SSE流式输出也有类似的雷区。SSE协议要求服务端每过一段时间就往客户端推数据、保持连接活跃。如果模型推理过程中有某个阶段“停顿”了很长时间——比如触发了工具调用等待入参、上下文太长正在整理压缩——导致100秒内没有任何响应字节推给Cloudflare边缘同样会被掐断。这类问题尤其隐蔽因为本地直连源站测试时一切正常套上Cloudflare之后才开始出现。2.2 大模型网关里最容易触雷的三种流量我在排障过程中总结了三种最容易撞上100秒限制的流量类型流量类型典型场景触发原因非流式长推理请求客户端关闭流式等最终结果整体返回源站整体响应时间超过100秒SSE流式推理中的停顿模型在工具调用、长上下文整理时暂停输出单次数据帧间隔超过100秒批量处理/离线任务接口批量向量化、批量精排、长文档分析单次后端处理时间超过100秒这里面最坑的是第二种。很多人测试SSE时只测“稳定输出”的场景数据一帧接一帧地推永远测不出问题。但真实用户的使用习惯不是这样他们会让模型写代码、调插件、琢磨半天再出结果。只要停顿超过100秒连接就会断。用户看到的就是“AI回复到一半就断了”他理解不了只会觉得你的服务不稳定。2.3 把超时调成参数是方向性错误遇到超时第一反应往往是“把连接超时调大一点”。客户端fetch加个timeout120Nginx把proxy_read_timeout调到600FastAPI设置keep_alive更长——这些操作在纯源站链路上确实有效但在Cloudflare后面全部失效。原因很简单超时发生在Cloudflare边缘节点它位于你的Nginx和客户端之间。你在源站把超时调得再大边缘节点到100秒照样掐线。这不是参数问题是链路问题。链路中间有一个你控制不了的设备而且这个设备又不通融那就只能换一条没有这个设备的链路。这是我从这次排障里得到的最重要的一条结论也直接决定了后面的选型方向。3. 完整排障链路从“怀疑后端”到“锁定边缘节点”3.1 现象连接总在80到100秒之间断先说现象。出问题的网关后面挂着一个兼容OpenAI接口的推理服务用户调用时只要生成逻辑比较长连接就会在80到100秒之间断开。当时收到的报错非常杂有人的Python requests看到的是Connection reset by peer有人用OpenAI SDK看到的是TimeoutError还有一部分用户走的是WebSocket通道反而一切正常。最有意思的一点是WebSocket不受影响。Cloudflare对WebSocket的处理走的是独立的升级通道和普通HTTP请求的转发策略不同。所以WebSocket正常反而成了一条重要线索连接断开不是源站的问题而是HTTP转发层的问题。3.2 证据链源站日志正常客户端确实断了接下来我把后端日志和网关访问日志拉出来对了一遍。源站那边清清楚楚记着请求200完成耗时104秒、106秒、112秒不等网关也记录了转发完成。但客户端这边的错误时间戳全都落在请求发起后的100秒附近。两边一对比结论已经八九不离十源站服务没有问题连接是在中途被某个中间设备掐断的。为了进一步验证我临时把网关绑到一个源站IP上让用户绕过域名解析直接IP访问。这一试问题彻底显形同一批大请求直连IP全部正常返回。那会儿我还没法断定是Cloudflare还是DNS但已经把范围缩小到“公网域名链路”这一层了。3.3 锁定用直连IP和不接边缘服务的域名做对比最后做了一个更严谨的对比测试三个入口同一个请求入口A域名走Cloudflare边缘节点结果100秒断入口B直接访问源站IPTLS用源站证书结果正常入口C用另一个不套边缘服务的域名指向同一源站结果正常。入口A断、B和C都通这就等于把故障精确锁定在了Cloudflare的边缘转发层上。后来我在Cloudflare的官方文档里确认了100秒限制的说明和现象完全吻合。到这里排障阶段算是画上了句号接下来就剩选型和迁移了。3.4 经验排超时问题永远先回答“谁先断的”这次排障给我最大的经验是遇到超时先不要着急改代码。先回答三个问题断的是哪一侧中间有没有不受控的设备源站日志和客户端错误时间戳能不能对得上把这三个问题回答完基本就能定位方向。如果一开始就埋头改后端超时参数很可能几天都找不到真正的根因。4. 从Cloudflare到OCI免费L7负载均衡器方案对比与决策逻辑4.1 CDN边缘和L7负载均衡器的本质区别不少人觉得负载均衡器不就是CDN的另一种叫法吗还真的不是。CDN的核心职责是缓存和就近分发设计目标是让静态资源离用户更近而L7负载均衡器的核心职责是流量分发、健康检查、SSL终止、会话保持它不缓存你的响应来了请求就转发给后端后端返回什么就是什么。对大模型网关而言缓存几乎没有意义——模型推理结果是动态生成的每个请求都不同缓存反而容易出脏数据。真正需要的是一个“稳定、透明、超时可调”的转发通道。L7负载均衡器正好干的是这件事。至于OCI的免费L7负载均衡器则是另一个层面的好消息Always Free资源里就包含弹性负载均衡器实例个人开发者和小团队完全可以把模型网关架到公网而不产生额外费用。4.2 OCI免费层能覆盖的边界具体来说OCI Always Free套餐里可用的是一个Flexible Load Balancer官方标称带宽在10Mbps这个级别以控制台实际额度为准对大模型API网关这种以少量长连接为主的场景是够用的。免费额度里通常还能包含一两台小型虚拟机意味着你可以在同一个网络区域里把“负载均衡 源站”整个拓扑都搭起来。需要说清楚的是这个方案适合的规模是小团队、个人开发者、内部工具、Demo项目。如果你要扛每秒几百上千的高并发那还是上付费实例更稳妥。但对于“把大模型网关从Cloudflare的100秒限制和端口锁死里解放出来”这件事免费层完全够用。我用下来的体感是个人项目和大模型灰度验证它比我预想的稳定得多。4.3 为什么说它是“终极破局”我把两个方案放在一起对比对比项Cloudflare方案OCI L7 LB方案等待源站响应上限100秒企业版才可调长可自行配置默认空闲超时300秒建议调至600秒以上可用端口免费层基本只放行80/443任意端口Listener和后端端口可互相映射缓存/改写响应有可能引入脏数据无纯转发后端真实IP容易被改写需要额外配置默认保留原始IP运维心智负担边缘规则多、限制多普通负载均衡器行为直观结论很清楚Cloudflare是一个优秀的边缘服务但它真的不是为长耗时API设计的而OCI的免费L7负载均衡器本质上就是一台“透明转发机器”端口自由、超时可控、不缓存不介入这才是大模型网关想要的入口层。5. OCI免费L7负载均衡器的落地步骤迁移实录5.1 整体架构从“三明治”变成“透明通道”迁移前客户端 → 域名DNS解析 → Cloudflare边缘节点 → 源站推理服务迁移后客户端 → 域名DNS解析 → OCI公网负载均衡器 → 源站推理服务这轮迁移只动DNS记录和入口层源站侧完全不动所以风险可控。整个过程可以分步执行出问题随时可以切回旧链路。5.2 创建负载均衡器的最小配置在OCI控制台创建负载均衡器我路过的最小配置是这样在“网络”菜单下找到“Load Balancers”点击“创建负载均衡器”。选择类型为Layer 7 Load Balancer应用负载均衡器。选择Always Free对应的弹性配置。网络规划时建议放在和源站同一个VCN或能路由到源站的子网这样后端通信走内网不占用公网带宽。添加Listener协议选HTTP或HTTPS端口按需填比如我用了一个非标准端口做灰度验证。配置后端集Backend Set指向源站的内网IP和实际监听端口。配置健康检查路径指向一个稳定的检查接口超时和间隔先用默认值跑稳了再调。后端集里有个容易被忽略的点后端端口不用和监听端口一致。监听端口是外网访问用的后端端口是源站实际监听的比如源站监听8080Listener监听443把两者通过后端集映射起来就行。端口自由的目标就是这样实现的。5.3 超时参数调整把空闲超时拉到600秒OCI负载均衡器默认的空闲超时通常是300秒这已经比Cloudflare的100秒宽裕不少但大模型推理场景下300秒也只是“够用”。我把Listener上的空闲超时调整到了600秒。这里的“空闲超时”含义是如果连接上一段时间没有任何数据传输LB就会主动关闭连接。大模型网关的SSE流式输出通常不会真的空闲太久但模型在思考阶段确实可能出现停顿所以给足600秒是合理的推荐值。如果你还要跑更重的离线批处理可以按需再往上调。需要注意不同服务商控制台上的参数名称可能不一样有的叫Idle Timeout有的叫Keepalive Timeout。配置前先确认自己调的是监听器级别的网络空闲超时而不是后端池的重试超时别调反了。5.4 域名和证书的处理后面要做的是把DNS从Cloudflare切到OCI LB的公网IP。我先把原本指向Cloudflare的A记录改成LB的IPTTL调短一些切完观察一段时间再调回正常TTL。证书方面我建议在OCI LB上做SSL终止证书可以用自有域名的正式证书也可以先生成一张自签证书用于联调。做了SSL终止之后源站可以继续走HTTP证书管理集中到LB这一层对源站的改动降到最小。如果你后续要做更复杂的双向TLS再单独调整。5.5 验证清单最后是验证。我实测的目标很明确长请求超过100秒不断、SSE流式输出稳定、WebSocket升级正常、真实IP能传到后端。简单列一下验证动作用一个需要110秒的非流式推理请求压一次确认能正常返回用SSE请求触发一次超过100秒的思考停顿确认连接不会被掐建立一条WebSocket长会话保持一段时间确认心跳和断线重连正常看后端日志确认收到的是真实客户端IP而不是LB的内部地址。全部通过迁移才算真正完成。6. 上线OCI LB后四个隐形坑比配置本身更值得注意6.1 健康检查只探路径不探业务我在源站上写了一个/health接口只返回ok。LB的健康检查一旦探测到HTTP 200就把流量放进去。但真正的模型服务可能因为显存不足、模型没加载、API进程卡死而处于“假死”状态。如果只依赖基础健康检查LB会在某台后端假死时仍然分配流量用户就会突然遇到一堆超时或者5xx。建议健康检查的探针接一个业务级接口这个接口返回的内容可以包括进程存活、依赖服务状态、模型是否已加载、显存余量。虽然是个人项目这个动作也能减少很多半夜被叫醒的机会。6.2 SSL终止位置决定后续扩展空间我把SSL终止放在LB上源站用HTTP。好处是证书管理集中、源站不用管TLS。但代价是如果以后要在源站和客户端之间做双向TLS或者需要源站自己判断TLS握手阶段的信息LB终止会让你拿不到原始TLS握手上下文。所以做这个选择时要想清楚未来会不会有这类需求不要单纯为了省事就全堆在LB上。6.3 WebSocket升级和SSE的监听器配置差异OCI L7 LB对WebSocket支持得不错基本上是开箱即用只要监听器协议配成HTTP或HTTPSLB会识别Upgrade请求并建立长连接。SSE也类似因为SSE本质上是普通HTTP响应带上text/event-stream。但有两点要记住一是在监听器里确认WebSocket支持已开启不同版本的控制台开关位置不太一样二是SSE的空闲超时和WebSocket的空闲超时可能各自独立配置不要只改HTTP的idle timeout就以为万事大吉。6.4 别忽略后端连接保持这个问题在压力测试时会突然爆发。客户端到LB、LB到源站是两段独立的TCP连接。如果后端服务的连接池没有开Keepalive每条请求都重新建TCP连接高并发下源站的TIME_WAIT连接会堆积得非常快。反正我在源站的Web服务里开了Keepalive并把keepalive_timeout设置得比LB的空闲超时短一些防止连接被LB先关掉导致源站频繁收到被动的连接重置。迁移之后的体感这次迁移过后我已经把所有新项目的大模型网关默认改成“域名解析到OCI免费L7负载均衡器”的打法了。Cloudflare那100秒的限制不是Bug而是它的产品设计取向对网站来说合理但大模型API网关不归它管硬套迟早出事。如果你也遇到“源站日志正常、客户端却断连”的问题建议顺着域名、端口、超时这条链路排查大概率能少熬一个凌晨班。最后再分享一个小技巧迁移前把健康检查接口写成业务级接口切换DNS后的第一个请求直接打到健康检查接口上看链路通没通比看一堆业务日志高效得多。
返回列表