feat(gateway): 添加流超时处理机制
- 添加 StreamTimeoutSettings 配置结构体和系统设置 - 实现 TimeoutCounterCache Redis 计数器用于累计超时次数 - 在 RateLimitService 添加 HandleStreamTimeout 方法 - 在 gateway_service、openai_gateway_service、antigravity_gateway_service 中调用超时处理 - 添加后端 API 端点 GET/PUT /admin/settings/stream-timeout - 添加前端配置界面到系统设置页面 - 支持配置:启用开关、超时阈值、处理方式、暂停时长、触发阈值、阈值窗口 默认配置: - 启用:true - 超时阈值:60秒 - 处理方式:临时不可调度 - 暂停时长:5分钟 - 触发阈值:3次 - 阈值窗口:10分钟
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
@@ -675,3 +676,99 @@ func (s *SettingService) GetLinuxDoConnectOAuthConfig(ctx context.Context) (conf
|
||||
|
||||
return effective, nil
|
||||
}
|
||||
|
||||
// GetStreamTimeoutSettings 获取流超时处理配置
|
||||
func (s *SettingService) GetStreamTimeoutSettings(ctx context.Context) (*StreamTimeoutSettings, error) {
|
||||
value, err := s.settingRepo.GetValue(ctx, SettingKeyStreamTimeoutSettings)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrSettingNotFound) {
|
||||
return DefaultStreamTimeoutSettings(), nil
|
||||
}
|
||||
return nil, fmt.Errorf("get stream timeout settings: %w", err)
|
||||
}
|
||||
if value == "" {
|
||||
return DefaultStreamTimeoutSettings(), nil
|
||||
}
|
||||
|
||||
var settings StreamTimeoutSettings
|
||||
if err := json.Unmarshal([]byte(value), &settings); err != nil {
|
||||
return DefaultStreamTimeoutSettings(), nil
|
||||
}
|
||||
|
||||
// 验证并修正配置值
|
||||
if settings.TimeoutSeconds < 0 {
|
||||
settings.TimeoutSeconds = 0
|
||||
}
|
||||
if settings.TimeoutSeconds > 0 && settings.TimeoutSeconds < 30 {
|
||||
settings.TimeoutSeconds = 30
|
||||
}
|
||||
if settings.TimeoutSeconds > 300 {
|
||||
settings.TimeoutSeconds = 300
|
||||
}
|
||||
if settings.TempUnschedMinutes < 1 {
|
||||
settings.TempUnschedMinutes = 1
|
||||
}
|
||||
if settings.TempUnschedMinutes > 60 {
|
||||
settings.TempUnschedMinutes = 60
|
||||
}
|
||||
if settings.ThresholdCount < 1 {
|
||||
settings.ThresholdCount = 1
|
||||
}
|
||||
if settings.ThresholdCount > 10 {
|
||||
settings.ThresholdCount = 10
|
||||
}
|
||||
if settings.ThresholdWindowMinutes < 1 {
|
||||
settings.ThresholdWindowMinutes = 1
|
||||
}
|
||||
if settings.ThresholdWindowMinutes > 60 {
|
||||
settings.ThresholdWindowMinutes = 60
|
||||
}
|
||||
|
||||
// 验证 action
|
||||
switch settings.Action {
|
||||
case StreamTimeoutActionTempUnsched, StreamTimeoutActionError, StreamTimeoutActionNone:
|
||||
// valid
|
||||
default:
|
||||
settings.Action = StreamTimeoutActionTempUnsched
|
||||
}
|
||||
|
||||
return &settings, nil
|
||||
}
|
||||
|
||||
// SetStreamTimeoutSettings 设置流超时处理配置
|
||||
func (s *SettingService) SetStreamTimeoutSettings(ctx context.Context, settings *StreamTimeoutSettings) error {
|
||||
if settings == nil {
|
||||
return fmt.Errorf("settings cannot be nil")
|
||||
}
|
||||
|
||||
// 验证配置值
|
||||
if settings.TimeoutSeconds < 0 {
|
||||
return fmt.Errorf("timeout_seconds must be non-negative")
|
||||
}
|
||||
if settings.TimeoutSeconds > 0 && (settings.TimeoutSeconds < 30 || settings.TimeoutSeconds > 300) {
|
||||
return fmt.Errorf("timeout_seconds must be 0 or between 30-300")
|
||||
}
|
||||
if settings.TempUnschedMinutes < 1 || settings.TempUnschedMinutes > 60 {
|
||||
return fmt.Errorf("temp_unsched_minutes must be between 1-60")
|
||||
}
|
||||
if settings.ThresholdCount < 1 || settings.ThresholdCount > 10 {
|
||||
return fmt.Errorf("threshold_count must be between 1-10")
|
||||
}
|
||||
if settings.ThresholdWindowMinutes < 1 || settings.ThresholdWindowMinutes > 60 {
|
||||
return fmt.Errorf("threshold_window_minutes must be between 1-60")
|
||||
}
|
||||
|
||||
switch settings.Action {
|
||||
case StreamTimeoutActionTempUnsched, StreamTimeoutActionError, StreamTimeoutActionNone:
|
||||
// valid
|
||||
default:
|
||||
return fmt.Errorf("invalid action: %s", settings.Action)
|
||||
}
|
||||
|
||||
data, err := json.Marshal(settings)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal stream timeout settings: %w", err)
|
||||
}
|
||||
|
||||
return s.settingRepo.Set(ctx, SettingKeyStreamTimeoutSettings, string(data))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user