fix: 修复语法问题
This commit is contained in:
23
.env.example
23
.env.example
@@ -38,26 +38,11 @@ REQUEST_TIMEOUT=30000
|
||||
# ===========================================
|
||||
# 性能优化配置
|
||||
# ===========================================
|
||||
# 最大连接数
|
||||
MAX_SOCKETS=100
|
||||
# 最大并发请求数
|
||||
MAX_CONCURRENT_REQUESTS=100
|
||||
|
||||
# 最大空闲连接数
|
||||
MAX_FREE_SOCKETS=20
|
||||
|
||||
# 启用 Keep-Alive
|
||||
ENABLE_KEEP_ALIVE=true
|
||||
|
||||
# 禁用压缩(减少CPU开销)
|
||||
DISABLE_COMPRESSION=true
|
||||
|
||||
# 缓冲区大小(字节,建议流式响应使用64KB或更大)
|
||||
BUFFER_SIZE=65536
|
||||
|
||||
# 流式传输缓冲区大小(字节,默认64KB)
|
||||
STREAM_BUFFER_SIZE=65536
|
||||
|
||||
# 流式请求响应头超时(毫秒,默认10秒)
|
||||
STREAM_HEADER_TIMEOUT=10000
|
||||
# 启用 Gzip 压缩
|
||||
ENABLE_GZIP=false
|
||||
|
||||
# ===========================================
|
||||
# 日志配置
|
||||
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 GPT-Load Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
22
README.md
22
README.md
@@ -187,20 +187,36 @@ make help # Show all commands
|
||||
```text
|
||||
/
|
||||
├── cmd/
|
||||
│ └── gpt-load/
|
||||
│ └── main.go # Main entry point
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ │ └── config.go # Configuration management
|
||||
│ │ └── manager.go # Configuration management
|
||||
│ ├── errors/
|
||||
│ │ └── errors.go # Custom error types
|
||||
│ ├── handler/
|
||||
│ │ └── handler.go # HTTP handlers
|
||||
│ ├── keymanager/
|
||||
│ │ └── keymanager.go # Key manager
|
||||
│ │ └── manager.go # Key manager
|
||||
│ ├── middleware/
|
||||
│ │ └── middleware.go # HTTP middleware
|
||||
│ └── proxy/
|
||||
│ └── proxy.go # Proxy server core
|
||||
│ └── server.go # Proxy server core
|
||||
├── pkg/
|
||||
│ └── types/
|
||||
│ └── interfaces.go # Common interfaces and types
|
||||
├── scripts/
|
||||
│ └── validate-keys.py # Key validation script
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── docker-build.yml # GitHub Actions CI/CD
|
||||
├── build/ # Build output directory
|
||||
├── .env.example # Configuration template
|
||||
├── Dockerfile # Docker build file
|
||||
├── docker-compose.yml # Docker Compose configuration
|
||||
├── Makefile # Build scripts
|
||||
├── go.mod # Go module file
|
||||
├── LICENSE # MIT License
|
||||
└── README.md # Project documentation
|
||||
```
|
||||
|
||||
|
22
README_CN.md
22
README_CN.md
@@ -187,20 +187,36 @@ make help # 显示所有命令
|
||||
```text
|
||||
/
|
||||
├── cmd/
|
||||
│ └── gpt-load/
|
||||
│ └── main.go # 主入口文件
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ │ └── config.go # 配置管理
|
||||
│ │ └── manager.go # 配置管理
|
||||
│ ├── errors/
|
||||
│ │ └── errors.go # 自定义错误类型
|
||||
│ ├── handler/
|
||||
│ │ └── handler.go # HTTP 处理器
|
||||
│ ├── keymanager/
|
||||
│ │ └── keymanager.go # 密钥管理器
|
||||
│ │ └── manager.go # 密钥管理器
|
||||
│ ├── middleware/
|
||||
│ │ └── middleware.go # HTTP 中间件
|
||||
│ └── proxy/
|
||||
│ └── proxy.go # 代理服务器核心
|
||||
│ └── server.go # 代理服务器核心
|
||||
├── pkg/
|
||||
│ └── types/
|
||||
│ └── interfaces.go # 通用接口和类型
|
||||
├── scripts/
|
||||
│ └── validate-keys.py # 密钥验证脚本
|
||||
├── .github/
|
||||
│ └── workflows/
|
||||
│ └── docker-build.yml # GitHub Actions CI/CD
|
||||
├── build/ # 构建输出目录
|
||||
├── .env.example # 配置文件模板
|
||||
├── Dockerfile # Docker 构建文件
|
||||
├── docker-compose.yml # Docker Compose 配置
|
||||
├── Makefile # 构建脚本
|
||||
├── go.mod # Go 模块文件
|
||||
├── LICENSE # MIT 许可证
|
||||
└── README.md # 项目文档
|
||||
```
|
||||
|
||||
|
@@ -107,6 +107,13 @@ func setupRoutes(handlers *handler.Handler, proxyServer *proxy.ProxyServer, conf
|
||||
|
||||
router := gin.New()
|
||||
|
||||
// Add server start time middleware for uptime calculation
|
||||
startTime := time.Now()
|
||||
router.Use(func(c *gin.Context) {
|
||||
c.Set("serverStartTime", startTime)
|
||||
c.Next()
|
||||
})
|
||||
|
||||
// Add middleware
|
||||
router.Use(middleware.Recovery())
|
||||
router.Use(middleware.Logger(configManager.GetLogConfig()))
|
||||
|
@@ -243,7 +243,16 @@ func parseBoolean(value string, defaultValue bool) bool {
|
||||
if value == "" {
|
||||
return defaultValue
|
||||
}
|
||||
return strings.ToLower(value) == "true"
|
||||
|
||||
lowerValue := strings.ToLower(value)
|
||||
switch lowerValue {
|
||||
case "true", "1", "yes", "on":
|
||||
return true
|
||||
case "false", "0", "no", "off":
|
||||
return false
|
||||
default:
|
||||
return defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
// parseArray parses array environment variable (comma-separated)
|
||||
|
@@ -39,12 +39,20 @@ func (h *Handler) Health(c *gin.Context) {
|
||||
httpStatus = http.StatusServiceUnavailable
|
||||
}
|
||||
|
||||
// Calculate uptime (this should be tracked from server start time)
|
||||
uptime := "unknown"
|
||||
if startTime, exists := c.Get("serverStartTime"); exists {
|
||||
if st, ok := startTime.(time.Time); ok {
|
||||
uptime = time.Since(st).String()
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(httpStatus, gin.H{
|
||||
"status": status,
|
||||
"timestamp": time.Now().UTC().Format(time.RFC3339),
|
||||
"healthy_keys": stats.HealthyKeys,
|
||||
"total_keys": stats.TotalKeys,
|
||||
"uptime": time.Since(time.Now()).String(), // This would need to be tracked properly
|
||||
"uptime": uptime,
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -306,12 +306,20 @@ func (km *Manager) GetBlacklist() []types.BlacklistEntry {
|
||||
|
||||
// setupMemoryCleanup sets up periodic memory cleanup
|
||||
func (km *Manager) setupMemoryCleanup() {
|
||||
km.cleanupTicker = time.NewTicker(5 * time.Minute)
|
||||
// Reduce GC frequency to every 15 minutes to avoid performance impact
|
||||
km.cleanupTicker = time.NewTicker(15 * time.Minute)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-km.cleanupTicker.C:
|
||||
// Only trigger GC if memory usage is high
|
||||
var m runtime.MemStats
|
||||
runtime.ReadMemStats(&m)
|
||||
// Trigger GC only if allocated memory is above 100MB
|
||||
if m.Alloc > 100*1024*1024 {
|
||||
runtime.GC()
|
||||
logrus.Debugf("Manual GC triggered, memory usage: %d MB", m.Alloc/1024/1024)
|
||||
}
|
||||
case <-km.stopCleanup:
|
||||
return
|
||||
}
|
||||
|
@@ -62,8 +62,12 @@ func Logger(config types.LogConfig) gin.HandlerFunc {
|
||||
retryInfo = fmt.Sprintf(" - Retry[%d]", retryCount)
|
||||
}
|
||||
|
||||
// Filter health check logs
|
||||
if path == "/health" {
|
||||
// Filter health check and other monitoring endpoint logs to reduce noise
|
||||
if isMonitoringEndpoint(path) {
|
||||
// Only log errors for monitoring endpoints
|
||||
if statusCode >= 400 {
|
||||
logrus.Warnf("%s %s - %d - %v", method, fullPath, statusCode, latency)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -257,3 +261,14 @@ func ErrorHandler() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isMonitoringEndpoint checks if the path is a monitoring endpoint
|
||||
func isMonitoringEndpoint(path string) bool {
|
||||
monitoringPaths := []string{"/health", "/stats", "/blacklist", "/reset-keys"}
|
||||
for _, monitoringPath := range monitoringPaths {
|
||||
if path == monitoringPath {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@@ -369,8 +369,8 @@ func (ps *ProxyServer) handleStreamingResponse(c *gin.Context, resp *http.Respon
|
||||
return
|
||||
}
|
||||
|
||||
// Copy streaming data
|
||||
buffer := make([]byte, 4096)
|
||||
// Copy streaming data with optimized buffer size
|
||||
buffer := make([]byte, 32*1024) // 32KB buffer for better performance
|
||||
for {
|
||||
n, err := resp.Body.Read(buffer)
|
||||
if n > 0 {
|
||||
|
Reference in New Issue
Block a user