Skip to content

Conversation

@OxalisCu
Copy link
Contributor

support first byte timeout for llm streaming requests

@CLAassistant
Copy link

CLAassistant commented Jul 23, 2025

CLA assistant check
All committers have signed the CLA.

@lingma-agents
Copy link

lingma-agents bot commented Jul 23, 2025

添加LLM流式请求的首包超时支持

变更概述

新功能

  • ProviderConfig配置增强
    • 新增firstByteTimeout字段(单位毫秒),用于设置流式请求的上游服务首包超时时间,默认值0表示不启用该功能。
    • 新增isStreamingAPI方法,通过API名称和请求体判断是否为流式请求:
      • CompletionChatCompletion等11个API类型,检查请求体中的stream字段布尔值;
      • GeminiStreamGenerateContent直接返回true
    • handleRequestBody中实现超时控制逻辑:
      • firstByteTimeout != 0且为流式API时,通过Envoy头x-envoy-upstream-rq-first-byte-timeout-ms设置超时值。
      • 使用strconv.FormatUint将配置值转换为字符串格式,并添加错误日志记录机制。

依赖更新

  • 新增对strconv包的导入,用于数值类型转换。

配置调整

  • FromJson方法中,新增对firstByteTimeout的解析逻辑,默认值0保持兼容性。
变更文件
文件路径 变更说明
plugins/​wasm-go/​extensions/​ai-proxy/​provider/​provider.​go 新增首包超时配置项、流式API判断逻辑及Envoy头设置功能
时序图
sequenceDiagram
    participant PC as ProviderConfig
    PC->>PC: handleRequestBody()
    PC->>PC: isStreamingAPI()
    alt 当isStreamingAPI返回true且firstByteTimeout不为0时
        PC->>Envoy: 设置x-envoy-upstream-rq-first-byte-timeout-ms头
        opt 设置失败时
            PC->>Log: 记录错误日志
        end
    else 否则
        PC->>PC: 继续原有处理流程
    end
Loading

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

Copy link

@lingma-agents lingma-agents bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔎 代码评审报告

🎯 评审意见概览
严重度 数量 说明
🔴 Blocker 0 阻断性问题,需立即修复。例如:系统崩溃、关键功能不可用或严重安全漏洞。
🟠 Critical 1 严重问题,高优先级修复。例如:核心功能异常或性能瓶颈影响用户体验。
🟡 Major 0 主要问题,建议修复。例如:非核心功能缺陷或代码维护性较差。
🟢 Minor 0 次要问题,酬情优化。例如:代码格式不规范或注释缺失。

总计: 1 个问题

📋 评审意见详情
💡 代码实现建议
以下是文件级别的代码建议,聚焦于代码的可读性、可维护性和潜在问题。
🔹 plugins/wasm-go/extensions/ai-proxy/provider/provider.go (1 💬)
🚀 架构设计建议
以下是对代码架构和设计的综合分析,聚焦于跨文件交互、系统一致性和潜在优化空间。
🔍1. 配置项验证缺失导致潜在数值溢出风险

新增的firstByteTimeout配置项使用uint32类型,但未在配置解析时进行数值范围校验。当用户配置超过uint32最大值(4294967295)时会导致数值截断,可能引发超时时间不符合预期的系统性问题。建议在ProviderConfig.FromJson方法中添加数值范围校验逻辑,确保配置值在0到4294967295之间。

📌 关键代码

c.firstByteTimeout = uint32(json.Get("firstByteTimeout").Uint())

⚠️ 潜在风险

配置值超过uint32最大值时导致数值截断,实际生效的超时时间可能与配置值不符,引发不可预期的请求超时行为

🔍2. 流式API判断逻辑存在硬编码扩展性问题

isStreamingAPI函数通过硬编码方式列举所有流式API名称,当新增流式API时需要修改该函数,违反开放封闭原则。建议将流式API列表抽离为可配置的常量集合或注册表,便于扩展和维护。当前实现中已包含9种API名称,后续扩展将导致频繁修改核心逻辑。

📌 关键代码

switch apiName {
case ApiNameCompletion,
    ApiNameChatCompletion,
    ApiNameImageGeneration,
    ...// 其他8个枚举值
}

⚠️ 潜在风险

新增流式API时需修改核心判断逻辑,增加维护成本并可能引入遗漏配置的风险

🔍3. 跨配置项逻辑冲突风险

现有配置包含timeout和firstByteTimeout两个超时配置,但未明确两者的作用域关系。需确认这两个超时配置是否会产生逻辑冲突(如总超时与首包超时的叠加效应),建议在配置文档中明确说明两者的协同工作机制及优先级规则。

📌 关键代码

// 现有配置字段
timeout uint32 `...`
firstByteTimeout uint32 `...`

⚠️ 潜在风险

未定义的超时配置交互可能导致请求处理逻辑不符合预期,引发不可预测的超时行为

🔍4. 缺少配置变更热加载验证

新增配置项firstByteTimeout未验证动态配置更新时的行为。需要确保当通过热加载更新该配置值时,能正确应用到后续请求处理中,避免配置更新后出现状态不一致的情况。

⚠️ 潜在风险

动态配置更新时可能无法及时生效,导致配置变更无法按预期生效

🔍5. 日志输出包含敏感配置信息

在841行直接输出firstByteTimeout数值到调试日志,可能在日志收集系统中暴露配置信息。建议对敏感配置值进行脱敏处理后再记录日志。

📌 关键代码

log.Debugf("[firstByteTimeout] %d", c.firstByteTimeout)

⚠️ 潜在风险

调试日志可能包含配置数值,存在信息泄露风险

审查详情
📒 文件清单 (1 个文件)
📝 变更: 1 个文件

📝 变更文件:

  • plugins/wasm-go/extensions/ai-proxy/provider/provider.go

💡 小贴士

与 lingma-agents 交流的方式

📜 直接回复评论
直接回复本条评论,lingma-agents 将自动处理您的请求。例如:

  • 在当前代码中添加详细的注释说明。

  • 请详细介绍一下你说的 LRU 改造方案,并使用伪代码加以说明。

📜 在代码行处标记
在文件的特定位置创建评论并 @lingma-agents。例如:

  • @lingma-agents 分析这个方法的性能瓶颈并提供优化建议。

  • @lingma-agents 对这个方法生成优化代码。

📜 在讨论中提问
在任何讨论中 @lingma-agents 来获取帮助。例如:

  • @lingma-agents 请总结上述讨论并提出解决方案。

  • @lingma-agents 请根据讨论内容生成优化代码。

c.timeout = defaultTimeout
}
// first byte timeout
c.firstByteTimeout = uint32(json.Get("firstByteTimeout").Uint())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为firstByteTimeout字段添加数值范围验证,防止配置值超出uint32最大值导致截断

🟠 Critical | 🐞 Bugs

📋 问题详情

当JSON配置中firstByteTimeout的值超过uint32最大值(4294967295)时,直接转换会导致数值截断为0。这可能使配置失效并引发隐蔽的逻辑错误,例如当用户配置4294967296时会被错误地解析为0,导致首包超时未生效。

💡 解决方案

当用户配置的firstByteTimeout值超过uint32最大值时,需主动截断并记录警告:

-c.firstByteTimeout = uint32(json.Get("firstByteTimeout").Uint())
+value := json.Get("firstByteTimeout").Uint()
+maxUint32 := ^uint32(0)
+if value > uint64(maxUint32) {
+    log.Warnf("firstByteTimeout value %d exceeds maximum allowed %d, using %d", value, maxUint32, maxUint32)
+    value = uint64(maxUint32)
+}
+c.firstByteTimeout = uint32(value)

您的反馈对我们很重要!(建议右键在新标签页中打开以下链接)

有用意见👍无用意见👎错误意见❌

Copy link
Collaborator

@johnlanni johnlanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@OxalisCu OxalisCu force-pushed the first-byte-timeout branch from d2aa345 to 5cacc15 Compare July 23, 2025 08:56
@OxalisCu OxalisCu force-pushed the first-byte-timeout branch from 5cacc15 to 0e96101 Compare July 23, 2025 09:05
@codecov-commenter
Copy link

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 46.05%. Comparing base (ef31e09) to head (0e96101).
Report is 617 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #2652       +/-   ##
===========================================
+ Coverage   35.91%   46.05%   +10.14%     
===========================================
  Files          69       81       +12     
  Lines       11576    13020     +1444     
===========================================
+ Hits         4157     5996     +1839     
+ Misses       7104     6679      -425     
- Partials      315      345       +30     

see 78 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

) (types.Action, error) {
// add the first byte timeout header to the request
if c.firstByteTimeout != 0 && c.isStreamingAPI(apiName, body) {
err := proxywasm.ReplaceHttpRequestHeader("x-envoy-upstream-rq-first-byte-timeout-ms", strconv.FormatUint(uint64(c.firstByteTimeout), 10))
Copy link
Collaborator

@cr7258 cr7258 Jul 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@OxalisCu Envoy 支持使用 x-envoy-upstream-rq-first-byte-timeout-ms 这个 header 来控制首包超时吗?我在文档里好像没看到这个参数:https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_filters/router_filter#http-headers-consumed-from-downstreams

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是 higress 自己新增的

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johnlanni johnlanni merged commit ea0bf7c into alibaba:main Jul 23, 2025
12 checks passed
ink-hz pushed a commit to ink-hz/higress-ai-capability-auth that referenced this pull request Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants