caidaohz commited on
Commit
dad2a85
·
1 Parent(s): 2c89095

✨ 更新性能指标,优化内存使用和错误率显示,确保精度提升至两位小数;增加API超时时间配置以支持长时间流式响应

Browse files
Files changed (3) hide show
  1. .gitignore +1 -0
  2. main.go +39 -17
  3. stats.go +7 -3
.gitignore CHANGED
@@ -108,3 +108,4 @@ api-proxy
108
  # Go coverage files
109
  *.out
110
  proxy-server
 
 
108
  # Go coverage files
109
  *.out
110
  proxy-server
111
+ deno-proxy
main.go CHANGED
@@ -44,11 +44,12 @@ var (
44
  "/cerebras": "https://api.cerebras.ai",
45
  }
46
  httpClient = &http.Client{
47
- Timeout: 30 * time.Second,
48
  Transport: &http.Transport{
49
- MaxIdleConns: 100,
50
- MaxIdleConnsPerHost: 100,
51
- IdleConnTimeout: 90 * time.Second,
 
52
  },
53
  }
54
  )
@@ -140,12 +141,6 @@ func (apc *AsyncProxyContext) StreamData(data []byte) error {
140
 
141
  // handleAPIProxy 处理API代理请求(异步优化版)
142
  func handleAPIProxy(c *gin.Context) {
143
- // 创建异步代理上下文
144
- asyncCtx := NewAsyncProxyContext(c, 60*time.Second) // 60秒超时
145
- defer asyncCtx.cancel()
146
-
147
- atomic.AddInt64(&requestCount, 1)
148
-
149
  path := c.Request.URL.Path
150
  prefix, rest := extractPrefixAndRest(path)
151
  if prefix == "" {
@@ -154,6 +149,13 @@ func handleAPIProxy(c *gin.Context) {
154
  return
155
  }
156
 
 
 
 
 
 
 
 
157
  // 异步记录请求,避免阻塞主流程
158
  go stats.recordRequest(prefix)
159
 
@@ -299,13 +301,7 @@ func apc_streamResponseBody(asyncCtx *AsyncProxyContext, resp *http.Response) er
299
  case <-asyncCtx.ctx.Done():
300
  return asyncCtx.ctx.Err()
301
  default:
302
- // 设置读取超时
303
- if deadline, ok := asyncCtx.ctx.Deadline(); ok {
304
- if tcpConn, ok := resp.Body.(interface{ SetReadDeadline(time.Time) error }); ok {
305
- tcpConn.SetReadDeadline(deadline)
306
- }
307
- }
308
-
309
  n, err := resp.Body.Read(buffer)
310
  if n > 0 {
311
  if streamErr := asyncCtx.StreamData(buffer[:n]); streamErr != nil {
@@ -612,6 +608,31 @@ func fastJSONPatch(bodyBytes []byte) ([]byte, error) {
612
  return json.Marshal(bodyJSON)
613
  }
614
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
615
  // main 主函数
616
  func main() {
617
  // 设置生产模式
@@ -671,6 +692,7 @@ func main() {
671
  log.Printf("🚀 API代理服务器已启动 (Go优化版) 端口:%s", port)
672
  log.Printf("🕒 统计数据每分钟自动刷新页面")
673
  log.Printf("⚡ 性能优化:异步统计、内存优化、锁竞争减少")
 
674
  log.Printf("📊 访问 http://localhost:%s 查看统计信息", port)
675
 
676
  // 使用自定义HTTP服务器以更好地控制
 
44
  "/cerebras": "https://api.cerebras.ai",
45
  }
46
  httpClient = &http.Client{
47
+ Timeout: 1800 * time.Second, // 增加到30分钟,适合长时间AI流式响应
48
  Transport: &http.Transport{
49
+ MaxIdleConns: 100,
50
+ MaxIdleConnsPerHost: 100,
51
+ IdleConnTimeout: 90 * time.Second,
52
+ ResponseHeaderTimeout: 30 * time.Second, // 只对响应头设置30秒超时
53
  },
54
  }
55
  )
 
141
 
142
  // handleAPIProxy 处理API代理请求(异步优化版)
143
  func handleAPIProxy(c *gin.Context) {
 
 
 
 
 
 
144
  path := c.Request.URL.Path
145
  prefix, rest := extractPrefixAndRest(path)
146
  if prefix == "" {
 
149
  return
150
  }
151
 
152
+ // 根据API端点设置合适的超时时间
153
+ timeout := getTimeoutForEndpoint(prefix)
154
+ asyncCtx := NewAsyncProxyContext(c, timeout)
155
+ defer asyncCtx.cancel()
156
+
157
+ atomic.AddInt64(&requestCount, 1)
158
+
159
  // 异步记录请求,避免阻塞主流程
160
  go stats.recordRequest(prefix)
161
 
 
301
  case <-asyncCtx.ctx.Done():
302
  return asyncCtx.ctx.Err()
303
  default:
304
+ // 对于流式响应,不设置严格的读取超时,让context控制整体超时
 
 
 
 
 
 
305
  n, err := resp.Body.Read(buffer)
306
  if n > 0 {
307
  if streamErr := asyncCtx.StreamData(buffer[:n]); streamErr != nil {
 
608
  return json.Marshal(bodyJSON)
609
  }
610
 
611
+ // getTimeoutForEndpoint 根据API端点返回合适的超时时间
612
+ func getTimeoutForEndpoint(prefix string) time.Duration {
613
+ // AI流式API需要更长的超时时间 - 30分钟
614
+ aiEndpoints := map[string]time.Duration{
615
+ "/openai": 1800 * time.Second, // 30分钟
616
+ "/claude": 1800 * time.Second, // 30分钟
617
+ "/gemini": 1800 * time.Second, // 30分钟
618
+ "/gnothink": 1800 * time.Second, // 30分钟
619
+ "/groq": 1800 * time.Second, // 30分钟
620
+ "/xai": 1800 * time.Second, // 30分钟
621
+ "/cohere": 1800 * time.Second, // 30分钟
622
+ "/together": 1800 * time.Second, // 30分钟
623
+ "/fireworks": 1800 * time.Second, // 30分钟
624
+ "/openrouter": 1800 * time.Second, // 30分钟
625
+ "/cerebras": 1800 * time.Second, // 30分钟
626
+ }
627
+
628
+ if timeout, exists := aiEndpoints[prefix]; exists {
629
+ return timeout
630
+ }
631
+
632
+ // 其他API使用较短的超时时间
633
+ return 60 * time.Second
634
+ }
635
+
636
  // main 主函数
637
  func main() {
638
  // 设置生产模式
 
692
  log.Printf("🚀 API代理服务器已启动 (Go优化版) 端口:%s", port)
693
  log.Printf("🕒 统计数据每分钟自动刷新页面")
694
  log.Printf("⚡ 性能优化:异步统计、内存优化、锁竞争减少")
695
+ log.Printf("⏱️ 超时配置:AI API 30分钟,其他API 1分钟,HTTP客户端 30分钟")
696
  log.Printf("📊 访问 http://localhost:%s 查看统计信息", port)
697
 
698
  // 使用自定义HTTP服务器以更好地控制
stats.go CHANGED
@@ -1,6 +1,7 @@
1
  package main
2
 
3
  import (
 
4
  "runtime"
5
  "sync"
6
  "sync/atomic"
@@ -241,7 +242,7 @@ func updatePerformanceMetrics() {
241
  var m runtime.MemStats
242
  runtime.ReadMemStats(&m)
243
 
244
- perfMetrics.MemoryUsageMB = float64(m.Alloc) / 1024 / 1024
245
  perfMetrics.GoroutineCount = runtime.NumGoroutine()
246
  perfMetrics.LastUpdated = now.UnixMilli()
247
 
@@ -281,6 +282,9 @@ func updatePerformanceMetrics() {
281
  perfMetrics.RequestsPerSec = 0.3*qps + 0.7*perfMetrics.RequestsPerSec
282
  }
283
 
 
 
 
284
  // 更新记录
285
  atomic.StoreInt64(&lastQPSUpdate, currentTime)
286
  atomic.StoreInt64(&lastRequestCount, currentRequests)
@@ -291,8 +295,8 @@ func updatePerformanceMetrics() {
291
  totalErrors := atomic.LoadInt64(&errorCount)
292
  if totalReqs > 0 {
293
  errorRate := float64(totalErrors) / float64(totalReqs) * 100
294
- // 四舍五入到2位小数
295
- perfMetrics.ErrorRate = float64(int(errorRate*100+0.5)) / 100
296
  }
297
 
298
  // 计算平均响应时间
 
1
  package main
2
 
3
  import (
4
+ "math"
5
  "runtime"
6
  "sync"
7
  "sync/atomic"
 
242
  var m runtime.MemStats
243
  runtime.ReadMemStats(&m)
244
 
245
+ perfMetrics.MemoryUsageMB = math.Round(float64(m.Alloc)/1024/1024*100) / 100
246
  perfMetrics.GoroutineCount = runtime.NumGoroutine()
247
  perfMetrics.LastUpdated = now.UnixMilli()
248
 
 
282
  perfMetrics.RequestsPerSec = 0.3*qps + 0.7*perfMetrics.RequestsPerSec
283
  }
284
 
285
+ // 保留2位小数
286
+ perfMetrics.RequestsPerSec = math.Round(perfMetrics.RequestsPerSec*100) / 100
287
+
288
  // 更新记录
289
  atomic.StoreInt64(&lastQPSUpdate, currentTime)
290
  atomic.StoreInt64(&lastRequestCount, currentRequests)
 
295
  totalErrors := atomic.LoadInt64(&errorCount)
296
  if totalReqs > 0 {
297
  errorRate := float64(totalErrors) / float64(totalReqs) * 100
298
+ // 使用math.Round保证精确的2位小数
299
+ perfMetrics.ErrorRate = math.Round(errorRate*100) / 100
300
  }
301
 
302
  // 计算平均响应时间