删除请求超时

This commit is contained in:
Sakurasan
2026-09-02 13:08:32 +08:00
parent 6d951a0d61
commit 923ac79039
5 changed files with 20 additions and 26 deletions
+2 -2
View File
@@ -27,7 +27,7 @@ OT_MASTER_KEY=change-me-master-key
OT_PROXY_UPSTREAM_KEY=
OT_PROXY_UPSTREAM_BASE_URL=https://api.openai.com
OT_PROXY_DEFAULT_MODEL=gpt-4o-mini
OT_PROXY_TIMEOUT=120s
OT_PROXY_TIMEOUT=300s
# 渠道健康检查
OT_PROXY_HEALTH_INTERVAL=60s
@@ -50,4 +50,4 @@ OT_ADMIN_EMAIL=admin@localhost
OT_ADMIN_PASSWORD=admin123
# 记录原始请求日志
OT_PROXY_LOG_RAW=false
OT_PROXY_LOG_RAW=false
+2 -2
View File
@@ -31,7 +31,7 @@ func serve() error {
}
defer a.Shutdown(context.Background())
gw := proxy.NewGateway(a.DB, a.Enc, a.Usage, a.Limit, cfg.RateLimit.UserRPS, cfg.Proxy.LogRaw)
gw := proxy.NewGateway(a.DB, a.Enc, a.Usage, a.Limit, cfg.RateLimit.UserRPS, cfg.Proxy.LogRaw, cfg.Proxy.Timeout)
router := api.NewRouter(a, gw)
srv := &http.Server{
@@ -59,4 +59,4 @@ func serve() error {
}
a.Usage.Close()
return nil
}
}
+9 -9
View File
@@ -59,14 +59,14 @@ type AuthConfig struct {
}
type ProxyConfig struct {
DefaultChannelName string // 首次启动自动创建的渠道名(如 openai)
UpstreamBaseURL string // 渠道 base_url 默认值
UpstreamKey string // 渠道上游 key 默认值
DefaultModel string // 渠道模型导入时使用的模型名
Timeout time.Duration
HealthInterval time.Duration // 渠道健康检查周期
HealthFailThreshold int // 连续失败 N 次进 cooldown
LogRaw bool // 记录管理员原始请求体+响应到 usage_logs(调试用,默认关)
DefaultChannelName string // 首次启动自动创建的渠道名(如 openai)
UpstreamBaseURL string // 渠道 base_url 默认值
UpstreamKey string // 渠道上游 key 默认值
DefaultModel string // 渠道模型导入时使用的模型名
Timeout time.Duration
HealthInterval time.Duration // 渠道健康检查周期
HealthFailThreshold int // 连续失败 N 次进 cooldown
LogRaw bool // 记录管理员原始请求体+响应到 usage_logs(调试用,默认关)
}
// loadDotEnv 读取 .env 并把 KEY=VALUE 注入环境变量(AutomaticEnv 自动映射 OT_ 前缀)。
@@ -127,7 +127,7 @@ func Load() (*Config, error) {
v.SetDefault("proxy.upstream_base_url", "https://api.openai.com")
v.SetDefault("proxy.upstream_key", "")
v.SetDefault("proxy.default_model", "gpt-4o-mini")
v.SetDefault("proxy.timeout", "120s")
v.SetDefault("proxy.timeout", "300s")
v.SetDefault("proxy.health_interval", "60s")
v.SetDefault("proxy.health_fail_threshold", 2)
v.SetDefault("proxy.log_raw", false)
+6 -6
View File
@@ -109,7 +109,7 @@ func contains(list []string, s string) bool {
return false
}
func NewGateway(db *gorm.DB, enc *crypto.Encryptor, rec *usage.Recorder, lim *ratelimit.Limiter, userRPS int, logRaw bool) *Gateway {
func NewGateway(db *gorm.DB, enc *crypto.Encryptor, rec *usage.Recorder, lim *ratelimit.Limiter, userRPS int, logRaw bool, gw_timeout time.Duration) *Gateway {
return &Gateway{
db: db,
ch: channel.NewService(db, enc),
@@ -118,7 +118,7 @@ func NewGateway(db *gorm.DB, enc *crypto.Encryptor, rec *usage.Recorder, lim *ra
lim: lim,
userRPS: userRPS,
logRaw: logRaw,
hc: &http.Client{Timeout: 120 * time.Second},
hc: &http.Client{Timeout: gw_timeout * time.Second},
}
}
@@ -272,10 +272,10 @@ func upstreamPath(proto string) string {
// upstreamPlan 描述一次代理请求的上游访问方式。
type upstreamPlan struct {
proto string // 上游协议(用于分协议 base_url)
path string // 上游路径
body []byte // 已转换的请求体
lineConv func([]byte) []byte // 流式逐行转换(nil=直通)
proto string // 上游协议(用于分协议 base_url)
path string // 上游路径
body []byte // 已转换的请求体
lineConv func([]byte) []byte // 流式逐行转换(nil=直通)
bodyConv func([]byte) ([]byte, error) // 非流式响应体转换(nil=直通)
}
+1 -7
View File
@@ -3,7 +3,6 @@ package proxy
import (
"bufio"
"bytes"
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
@@ -218,9 +217,7 @@ func (g *Gateway) proxyOne(c *gin.Context, ch *store.Channel, plan *upstreamPlan
}
}
ctx, cancel := context.WithTimeout(c.Request.Context(), time.Duration(ch.TimeoutMS)*time.Millisecond)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodPost, upstreamURL(ch, plan.proto, plan.path), bytes.NewReader(upBody))
req, err := http.NewRequest(http.MethodPost, upstreamURL(ch, plan.proto, plan.path), bytes.NewReader(upBody))
if err != nil {
return false, false, http.StatusInternalServerError, []byte("failed to build upstream request")
}
@@ -242,9 +239,6 @@ func (g *Gateway) proxyOne(c *gin.Context, ch *store.Channel, plan *upstreamPlan
start := time.Now()
resp, err := g.hc.Do(req)
if err != nil {
if ctx.Err() == context.DeadlineExceeded {
return false, true, http.StatusGatewayTimeout, []byte("upstream request timed out")
}
return false, true, http.StatusBadGateway, []byte("upstream request failed: " + err.Error())
}
defer resp.Body.Close()