refactor: 重构项目结构

This commit is contained in:
tbphp
2025-06-09 21:50:18 +08:00
parent 2470292662
commit 0c5cf4266d
14 changed files with 1964 additions and 1646 deletions

224
cmd/gpt-load/main.go Normal file
View File

@@ -0,0 +1,224 @@
// Package main provides the entry point for the GPT-Load proxy server
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"gpt-load/internal/config"
"gpt-load/internal/handler"
"gpt-load/internal/keymanager"
"gpt-load/internal/middleware"
"gpt-load/internal/proxy"
"gpt-load/pkg/types"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
)
func main() {
// Load configuration
configManager, err := config.NewManager()
if err != nil {
logrus.Fatalf("Failed to load configuration: %v", err)
}
// Setup logger
setupLogger(configManager)
// Display startup information
displayStartupInfo(configManager)
// Create key manager
keyManager, err := keymanager.NewManager(configManager.GetKeysConfig())
if err != nil {
logrus.Fatalf("Failed to create key manager: %v", err)
}
defer keyManager.Close()
// Create proxy server
proxyServer, err := proxy.NewProxyServer(keyManager, configManager)
if err != nil {
logrus.Fatalf("Failed to create proxy server: %v", err)
}
defer proxyServer.Close()
// Create handlers
handlers := handler.NewHandler(keyManager, configManager)
// Setup routes
router := setupRoutes(handlers, proxyServer, configManager)
// Create HTTP server with optimized timeout configuration
serverConfig := configManager.GetServerConfig()
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", serverConfig.Host, serverConfig.Port),
Handler: router,
ReadTimeout: 60 * time.Second, // Increased read timeout for large file uploads
WriteTimeout: 300 * time.Second, // Increased write timeout for streaming responses
IdleTimeout: 120 * time.Second, // Increased idle timeout for connection reuse
MaxHeaderBytes: 1 << 20, // 1MB header limit
}
// Start server
go func() {
logrus.Info("GPT-Load proxy server started successfully")
logrus.Infof("Server address: http://%s:%d", serverConfig.Host, serverConfig.Port)
logrus.Infof("Statistics: http://%s:%d/stats", serverConfig.Host, serverConfig.Port)
logrus.Infof("Health check: http://%s:%d/health", serverConfig.Host, serverConfig.Port)
logrus.Infof("Reset keys: http://%s:%d/reset-keys", serverConfig.Host, serverConfig.Port)
logrus.Infof("Blacklist query: http://%s:%d/blacklist", serverConfig.Host, serverConfig.Port)
logrus.Info("")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logrus.Fatalf("Server startup failed: %v", err)
}
}()
// Wait for interrupt signal to gracefully shutdown the server
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logrus.Info("Shutting down server...")
// Give outstanding requests a deadline for completion
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Attempt graceful shutdown
if err := server.Shutdown(ctx); err != nil {
logrus.Errorf("Server forced to shutdown: %v", err)
} else {
logrus.Info("Server exited gracefully")
}
}
// setupRoutes configures the HTTP routes
func setupRoutes(handlers *handler.Handler, proxyServer *proxy.ProxyServer, configManager types.ConfigManager) *gin.Engine {
// Set Gin mode
gin.SetMode(gin.ReleaseMode)
router := gin.New()
// Add middleware
router.Use(middleware.Recovery())
router.Use(middleware.Logger(configManager.GetLogConfig()))
router.Use(middleware.CORS(configManager.GetCORSConfig()))
router.Use(middleware.RateLimiter(configManager.GetPerformanceConfig()))
// Add authentication middleware if enabled
if configManager.GetAuthConfig().Enabled {
router.Use(middleware.Auth(configManager.GetAuthConfig()))
}
// Management endpoints
router.GET("/health", handlers.Health)
router.GET("/stats", handlers.Stats)
router.GET("/blacklist", handlers.Blacklist)
router.GET("/reset-keys", handlers.ResetKeys)
router.GET("/config", handlers.GetConfig) // Debug endpoint
// Handle 404 and 405
router.NoRoute(handlers.NotFound)
router.NoMethod(handlers.MethodNotAllowed)
// Proxy all other requests
router.NoRoute(proxyServer.HandleProxy)
return router
}
// setupLogger configures the logging system
func setupLogger(configManager types.ConfigManager) {
logConfig := configManager.GetLogConfig()
// Set log level
level, err := logrus.ParseLevel(logConfig.Level)
if err != nil {
logrus.Warn("Invalid log level, using info")
level = logrus.InfoLevel
}
logrus.SetLevel(level)
// Set log format
if logConfig.Format == "json" {
logrus.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: time.RFC3339,
})
} else {
logrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
TimestampFormat: "2006-01-02 15:04:05",
})
}
// Setup file logging if enabled
if logConfig.EnableFile {
// Create log directory if it doesn't exist
logDir := filepath.Dir(logConfig.FilePath)
if err := os.MkdirAll(logDir, 0755); err != nil {
logrus.Warnf("Failed to create log directory: %v", err)
} else {
// Open log file
logFile, err := os.OpenFile(logConfig.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
logrus.Warnf("Failed to open log file: %v", err)
} else {
// Use both file and stdout
logrus.SetOutput(io.MultiWriter(os.Stdout, logFile))
}
}
}
}
// displayStartupInfo shows startup information
func displayStartupInfo(configManager types.ConfigManager) {
serverConfig := configManager.GetServerConfig()
keysConfig := configManager.GetKeysConfig()
openaiConfig := configManager.GetOpenAIConfig()
authConfig := configManager.GetAuthConfig()
corsConfig := configManager.GetCORSConfig()
perfConfig := configManager.GetPerformanceConfig()
logConfig := configManager.GetLogConfig()
logrus.Info("Current Configuration:")
logrus.Infof(" Server: %s:%d", serverConfig.Host, serverConfig.Port)
logrus.Infof(" Keys file: %s", keysConfig.FilePath)
logrus.Infof(" Start index: %d", keysConfig.StartIndex)
logrus.Infof(" Blacklist threshold: %d errors", keysConfig.BlacklistThreshold)
logrus.Infof(" Max retries: %d", keysConfig.MaxRetries)
logrus.Infof(" Upstream URL: %s", openaiConfig.BaseURL)
logrus.Infof(" Request timeout: %dms", openaiConfig.Timeout)
authStatus := "disabled"
if authConfig.Enabled {
authStatus = "enabled"
}
logrus.Infof(" Authentication: %s", authStatus)
corsStatus := "disabled"
if corsConfig.Enabled {
corsStatus = "enabled"
}
logrus.Infof(" CORS: %s", corsStatus)
logrus.Infof(" Max concurrent requests: %d", perfConfig.MaxConcurrentRequests)
gzipStatus := "disabled"
if perfConfig.EnableGzip {
gzipStatus = "enabled"
}
logrus.Infof(" Gzip compression: %s", gzipStatus)
requestLogStatus := "enabled"
if !logConfig.EnableRequest {
requestLogStatus = "disabled"
}
logrus.Infof(" Request logging: %s", requestLogStatus)
}

View File

@@ -1,139 +0,0 @@
// Package main OpenAI多密钥代理服务器主入口
// @author OpenAI Proxy Team
// @version 2.0.0
package main
import (
"context"
"fmt"
"io"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
"openai-multi-key-proxy/internal/config"
"openai-multi-key-proxy/internal/proxy"
"github.com/sirupsen/logrus"
)
func main() {
// 加载配置
cfg, err := config.LoadConfig()
if err != nil {
logrus.Fatalf("加载配置失败: %v", err)
}
// 配置日志
setupLogger(cfg)
// 显示启动信息
displayStartupInfo(cfg)
// 创建代理服务器
proxyServer, err := proxy.NewProxyServer()
if err != nil {
logrus.Fatalf("❌ 创建代理服务器失败: %v", err)
}
defer proxyServer.Close()
// 设置路由
router := proxyServer.SetupRoutes()
// 创建HTTP服务器优化超时配置
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", cfg.Server.Host, cfg.Server.Port),
Handler: router,
ReadTimeout: 60 * time.Second, // 增加读超时,支持大文件上传
WriteTimeout: 300 * time.Second, // 增加写超时,支持流式响应
IdleTimeout: 120 * time.Second, // 增加空闲超时,复用连接
MaxHeaderBytes: 1 << 20, // 1MB header limit
}
// 启动服务器
go func() {
logrus.Infof("🚀 OpenAI 多密钥代理服务器启动成功")
logrus.Infof("📡 服务地址: http://%s:%d", cfg.Server.Host, cfg.Server.Port)
logrus.Infof("📊 统计信息: http://%s:%d/stats", cfg.Server.Host, cfg.Server.Port)
logrus.Infof("💚 健康检查: http://%s:%d/health", cfg.Server.Host, cfg.Server.Port)
logrus.Infof("🔄 重置密钥: http://%s:%d/reset-keys", cfg.Server.Host, cfg.Server.Port)
logrus.Infof("🚫 黑名单查询: http://%s:%d/blacklist", cfg.Server.Host, cfg.Server.Port)
logrus.Info("")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
logrus.Fatalf("❌ 服务器启动失败: %v", err)
}
}()
// 等待中断信号
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
logrus.Info("🛑 收到关闭信号,正在优雅关闭服务器...")
// 优雅关闭
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
logrus.Errorf("❌ 服务器关闭失败: %v", err)
} else {
logrus.Info("✅ 服务器已优雅关闭")
}
}
// displayStartupInfo 显示启动信息
func displayStartupInfo(cfg *config.Config) {
logrus.Info("🚀 OpenAI 多密钥代理服务器 v2.0.0 (Go版本)")
logrus.Info("")
// 显示配置
config.DisplayConfig(cfg)
logrus.Info("")
}
// setupLogger 配置日志系统
func setupLogger(cfg *config.Config) {
// 设置日志级别
level, err := logrus.ParseLevel(cfg.Log.Level)
if err != nil {
logrus.Warnf("无效的日志级别 '%s',使用默认级别 info", cfg.Log.Level)
level = logrus.InfoLevel
}
logrus.SetLevel(level)
// 设置日志格式
switch cfg.Log.Format {
case "json":
logrus.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
default:
logrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
ForceColors: true,
TimestampFormat: "2006-01-02 15:04:05",
})
}
// 配置文件日志
if cfg.Log.EnableFile {
// 创建日志目录
if err := os.MkdirAll(filepath.Dir(cfg.Log.FilePath), 0755); err != nil {
logrus.Warnf("创建日志目录失败: %v", err)
} else {
// 打开日志文件
file, err := os.OpenFile(cfg.Log.FilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
logrus.Warnf("打开日志文件失败: %v", err)
} else {
// 同时输出到控制台和文件
logrus.SetOutput(io.MultiWriter(os.Stdout, file))
}
}
}
}