diff --git a/.env.example b/.env.example index e3917db..bc704ba 100644 --- a/.env.example +++ b/.env.example @@ -1,27 +1,22 @@ # 服务器配置 PORT=3001 HOST=0.0.0.0 -IS_SLAVE=false # 服务器读取、写入和空闲连接的超时时间(秒) -SERVER_READ_TIMEOUT=120 +SERVER_READ_TIMEOUT=60 SERVER_WRITE_TIMEOUT=600 -SERVER_GRACEFUL_SHUTDOWN_TIMEOUT=30 SERVER_IDLE_TIMEOUT=120 +SERVER_GRACEFUL_SHUTDOWN_TIMEOUT=10 + +# 从节点标识 +IS_SLAVE=false + +# 时区 +TZ=Asia/Shanghai # 认证配置 是必需的,用于保护管理 API 和 UI 界面 AUTH_KEY=sk-123456 -# CORS配置 -ENABLE_CORS=true -ALLOWED_ORIGINS=* -ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS -ALLOWED_HEADERS=* -ALLOW_CREDENTIALS=false - -# 并发数量 -MAX_CONCURRENT_REQUESTS=100 - # 数据库配置 # 示例 DSN: user:password@tcp(localhost:3306)/gpt_load?charset=utf8mb4&parseTime=True&loc=Local DATABASE_DSN=root:123456@tcp(mysql:3306)/gpt_load?charset=utf8mb4&parseTime=True&loc=Local @@ -30,8 +25,18 @@ DATABASE_DSN=root:123456@tcp(mysql:3306)/gpt_load?charset=utf8mb4&parseTime=True # 示例 DSN: redis://:password@localhost:6379/0 REDIS_DSN=redis://redis:6379/0 +# 并发数量 +MAX_CONCURRENT_REQUESTS=100 + +# CORS配置 +ENABLE_CORS=true +ALLOWED_ORIGINS=* +ALLOWED_METHODS=GET,POST,PUT,DELETE,OPTIONS +ALLOWED_HEADERS=* +ALLOW_CREDENTIALS=false + # 日志配置 LOG_LEVEL=info LOG_FORMAT=text LOG_ENABLE_FILE=false -LOG_FILE_PATH= +LOG_FILE_PATH=logs/app.log diff --git a/Makefile b/Makefile index 1185765..13487b3 100644 --- a/Makefile +++ b/Makefile @@ -1,42 +1,6 @@ -# 变量定义 -BINARY_NAME=gpt-load -MAIN_PATH=./ -BUILD_DIR=./build -VERSION=2.0.0 -LDFLAGS=-ldflags "-X main.Version=$(VERSION) -s -w" - -# 从 .env 文件加载环境变量,如果不存在则使用默认值 -HOST ?= $(shell sed -n 's/^HOST=//p' .env 2>/dev/null || echo "localhost") -PORT ?= $(shell sed -n 's/^PORT=//p' .env 2>/dev/null || echo "3000") -API_BASE_URL=http://$(HOST):$(PORT) - # 默认目标 .DEFAULT_GOAL := help -.PHONY: all -all: clean build ## 清理并构建项目 - -# ============================================================================== -# 构建相关命令 -# ============================================================================== -.PHONY: build -build: ## 构建二进制文件 - @echo "🔨 构建 $(BINARY_NAME)..." - @mkdir -p $(BUILD_DIR) - go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME) $(MAIN_PATH) - @echo "✅ 构建完成: $(BUILD_DIR)/$(BINARY_NAME)" - -.PHONY: build-all -build-all: clean ## 为所有支持的平台构建二进制文件 - @echo "🔨 构建所有平台版本..." - @mkdir -p $(BUILD_DIR) - GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-amd64 $(MAIN_PATH) - GOOS=linux GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-linux-arm64 $(MAIN_PATH) - GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-amd64 $(MAIN_PATH) - GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-darwin-arm64 $(MAIN_PATH) - GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/$(BINARY_NAME)-windows-amd64.exe $(MAIN_PATH) - @echo "✅ 所有平台构建完成" - # ============================================================================== # 运行与开发 # ============================================================================== @@ -46,159 +10,12 @@ run: ## 构建前端并运行服务器 cd web && npm install && npm run build @echo "--- Preparing backend... ---" @echo "--- Starting backend... ---" - go run $(MAIN_PATH)/main.go + go run ./main.go .PHONY: dev dev: ## 以开发模式运行(带竞态检测) @echo "🔧 开发模式启动..." - go run -race $(MAIN_PATH)/main.go - -# ============================================================================== -# 测试与代码质量 -# ============================================================================== -.PHONY: test -test: ## 运行所有测试 - @echo "🧪 运行测试..." - go test -v -race -coverprofile=coverage.out ./... - -.PHONY: coverage -coverage: test ## 生成并查看测试覆盖率报告 - @echo "📊 生成测试覆盖率报告..." - go tool cover -html=coverage.out -o coverage.html - @echo "✅ 覆盖率报告生成: coverage.html" - -.PHONY: bench -bench: ## 运行基准测试 - @echo "⚡ 运行基准测试..." - go test -bench=. -benchmem ./... - -.PHONY: lint -lint: ## 使用 golangci-lint 检查代码 - @echo "🔍 代码检查..." - @if command -v golangci-lint >/dev/null 2>&1; then \ - golangci-lint run; \ - else \ - echo "⚠️ golangci-lint 未安装,跳过代码检查"; \ - echo "安装命令: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest"; \ - fi - -.PHONY: fmt -fmt: ## 格式化 Go 代码 - @echo "🎨 格式化代码..." - go fmt ./... - @if command -v goimports >/dev/null 2>&1; then \ - goimports -w .; \ - else \ - echo "💡 建议安装 goimports: go install golang.org/x/tools/cmd/goimports@latest"; \ - fi - -.PHONY: tidy -tidy: ## 整理和验证模块依赖 - @echo "📦 整理依赖..." - go mod tidy - go mod verify - -.PHONY: deps -deps: ## 下载模块依赖 - @echo "📥 安装依赖..." - go mod download - -# ============================================================================== -# 清理与安装 -# ============================================================================== -.PHONY: clean -clean: ## 清理所有构建产物 - @echo "🧹 清理构建文件..." - rm -rf $(BUILD_DIR) - rm -f coverage.out coverage.html - -.PHONY: install -install: build ## 构建并安装二进制文件到 /usr/local/bin - @echo "📦 安装到系统..." - sudo cp $(BUILD_DIR)/$(BINARY_NAME) /usr/local/bin/ - @echo "✅ 安装完成: /usr/local/bin/$(BINARY_NAME)" - -.PHONY: uninstall -uninstall: ## 从 /usr/local/bin 卸载二进制文件 - @echo "🗑️ 从系统卸载..." - sudo rm -f /usr/local/bin/$(BINARY_NAME) - @echo "✅ 卸载完成" - -# ============================================================================== -# Docker 相关命令 -# ============================================================================== -.PHONY: docker-build -docker-build: ## 构建 Docker 镜像 - @echo "🐳 构建 Docker 镜像..." - docker build -t gpt-load:$(VERSION) . - docker tag gpt-load:$(VERSION) gpt-load:latest - @echo "✅ Docker 镜像构建完成" - -.PHONY: docker-run -docker-run: ## 使用预构建镜像运行 Docker 容器 - @echo "🐳 运行 Docker 容器(预构建镜像)..." - docker run -d \ - --name gpt-load \ - -p 3000:3000 \ - -v $(PWD)/keys.txt:/app/keys.txt:ro \ - -v $(PWD)/.env:/app/.env:ro \ - --restart unless-stopped \ - ghcr.io/tbphp/gpt-load:latest - -.PHONY: docker-run-local -docker-run-local: ## 使用本地构建的镜像运行 Docker 容器 - @echo "🐳 运行 Docker 容器(本地构建)..." - docker run -d \ - --name gpt-load-local \ - -p 3000:3000 \ - -v $(PWD)/keys.txt:/app/keys.txt:ro \ - -v $(PWD)/.env:/app/.env:ro \ - --restart unless-stopped \ - gpt-load:latest - -.PHONY: compose-up -compose-up: ## 使用 Docker Compose 启动(预构建镜像) - @echo "🐳 使用 Docker Compose 启动(预构建镜像)..." - docker-compose up -d - -.PHONY: compose-up-dev -compose-up-dev: ## 使用 Docker Compose 启动(本地构建) - @echo "🐳 使用 Docker Compose 启动(本地构建)..." - docker-compose -f docker-compose.dev.yml up -d - -.PHONY: compose-down -compose-down: ## 停止所有 Docker Compose 服务 - @echo "🐳 停止 Docker Compose..." - docker-compose down - docker-compose -f docker-compose.dev.yml down 2>/dev/null || true - -# ============================================================================== -# 服务管理与工具 -# ============================================================================== -.PHONY: validate-keys -validate-keys: ## 验证 API 密钥的有效性 - @echo "🐍 使用 Python 版本验证密钥..." - python3 scripts/validate-keys.py -c 100 -t 15 - -.PHONY: health -health: ## 检查服务的健康状况 - @echo "💚 健康检查..." - @curl -s $(API_BASE_URL)/health | jq . || echo "请安装 jq 或检查服务是否运行" - -.PHONY: stats -stats: ## 查看服务的统计信息 - @echo "📊 查看统计信息..." - @curl -s $(API_BASE_URL)/stats | jq . || echo "请安装 jq 或检查服务是否运行" - -.PHONY: reset-keys -reset-keys: ## 重置所有密钥的状态 - @echo "🔄 重置密钥状态..." - @curl -s $(API_BASE_URL)/reset-keys | jq . || echo "请安装 jq 或检查服务是否运行" - -.PHONY: blacklist -blacklist: ## 查看当前黑名单中的密钥 - @echo "🚫 查看黑名单..." - @curl -s $(API_BASE_URL)/blacklist | jq . || echo "请安装 jq 或检查服务是否运行" + go run -race ./main.go .PHONY: help help: ## 显示此帮助信息 diff --git a/README.md b/README.md index 0e6732d..df848d1 100644 --- a/README.md +++ b/README.md @@ -2,60 +2,79 @@ [中文文档](README_CN.md) | English -![Docker Build](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml/badge.svg) -![Go Version](https://img.shields.io/badge/Go-1.21+-blue.svg) +[![Release](https://img.shields.io/github/v/release/tbphp/gpt-load)](https://github.com/tbphp/gpt-load/releases) +[![Build Docker Image](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml/badge.svg)](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml) +![Go Version](https://img.shields.io/badge/Go-1.23+-blue.svg) ![License](https://img.shields.io/badge/license-MIT-green.svg) -A high-performance proxy server for OpenAI-compatible APIs with multi-key rotation and load balancing, built with Go. +A high-performance, enterprise-grade AI API transparent proxy service designed specifically for enterprises and developers who need to integrate multiple AI services. Built with Go, featuring intelligent key management, load balancing, and comprehensive monitoring capabilities, designed for high-concurrency production environments. + +For detailed documentation, please visit [Official Documentation](https://www.gpt-load.com/docs) ## Features -- **Multi-key Rotation**: Automatic API key rotation with load balancing -- **Multi-Target Load Balancing**: Supports round-robin load balancing across multiple upstream API targets -- **Intelligent Blacklisting**: Distinguishes between permanent and temporary errors for smart key management -- **Real-time Monitoring**: Comprehensive statistics, health checks, and blacklist management -- **Flexible Configuration**: Environment-based configuration with .env file support -- **CORS Support**: Full cross-origin request support -- **Structured Logging**: Detailed logging with response times and key information -- **Optional Authentication**: Project-level Bearer token authentication -- **High Performance**: Zero-copy streaming, concurrent processing, and atomic operations -- **Production Ready**: Graceful shutdown, error recovery, and memory management +- **Transparent Proxy**: Complete preservation of native API formats, supporting OpenAI and Google Gemini among other formats (continuously expanding) +- **Intelligent Key Management**: High-performance key pool with group-based management, automatic rotation, and failure recovery +- **Load Balancing**: Weighted load balancing across multiple upstream endpoints to enhance service availability +- **Smart Failure Handling**: Automatic key blacklist management and recovery mechanisms to ensure service continuity +- **Dynamic Configuration**: System settings and group configurations support hot-reload without requiring restarts +- **Enterprise Architecture**: Distributed leader-follower deployment supporting horizontal scaling and high availability +- **Modern Management**: Vue 3-based web management interface that is intuitive and user-friendly +- **Comprehensive Monitoring**: Real-time statistics, health checks, and detailed request logging +- **High-Performance Design**: Zero-copy streaming, connection pool reuse, and atomic operations +- **Production Ready**: Graceful shutdown, error recovery, and comprehensive security mechanisms + +## Supported AI Services + +GPT-Load serves as a transparent proxy service, completely preserving the native API formats of various AI service providers: + +- **OpenAI Format**: Official OpenAI API, Azure OpenAI, and other OpenAI-compatible services +- **Google Gemini Format**: Native APIs for Gemini Pro, Gemini Pro Vision, and other models +- **Extensibility**: Plugin-based architecture design for rapid integration of new AI service providers and their native formats ## Quick Start -### Prerequisites +### System Requirements -- Go 1.21+ (for building from source) +- Go 1.23+ (for source builds) - Docker (for containerized deployment) +- MySQL 8.2+ (for database storage) +- Redis (for caching and distributed coordination, optional) -### Option 1: Using Docker (Recommended) +### Method 1: Using Docker Compose (Recommended) ```bash -# Pull the latest image -docker pull ghcr.io/tbphp/gpt-load:latest +# Download configuration files +wget https://raw.githubusercontent.com/tbphp/gpt-load/refs/heads/main/docker-compose.yml +wget -O .env https://raw.githubusercontent.com/tbphp/gpt-load/refs/heads/main/.env.example -# Create keys.txt file with your API keys (one per line) -echo "sk-your-api-key-1" > keys.txt -echo "sk-your-api-key-2" >> keys.txt +# Edit configuration file (modify service port and authentication key as needed) +vim .env -# Run the container -docker run -d -p 3000:3000 \ - -v $(pwd)/keys.txt:/app/keys.txt:ro \ - --name gpt-load \ - ghcr.io/tbphp/gpt-load:latest +# Start services (includes MySQL and Redis) +docker compose up -d + +# Check service status +docker compose ps + +# View logs +docker compose logs -f gpt-load + +# Common operations +docker compose restart gpt-load # Restart service +docker compose pull && docker compose down && docker compose up -d # Update to latest version ``` -### Option 2: Using Docker Compose +After deployment: -```bash -# Start the service -docker-compose up -d +- Access Web Management Interface: +- API Proxy Address: -# Stop the service -docker-compose down -``` +> Use the default authentication key `sk-123456` to login to the management interface. The authentication key can be modified via AUTH_KEY in the .env file. -### Option 3: Build from Source +### Method 2: Source Build + +Source build requires locally installed MySQL and Redis (optional). ```bash # Clone and build @@ -65,213 +84,270 @@ go mod tidy # Create configuration cp .env.example .env -echo "sk-your-api-key" > keys.txt + +# Modify DATABASE_DSN and REDIS_DSN configurations in .env +# REDIS_DSN is optional; if not configured, memory storage will be enabled # Run make run ``` -## Configuration +After deployment: -### Supported API Providers +- Access Web Management Interface: +- API Proxy Address: -This proxy server works with any OpenAI-compatible API, including: +> Use the default authentication key `sk-123456` to login to the management interface. The authentication key can be modified via AUTH_KEY in the .env file. -- **OpenAI**: `https://api.openai.com` -- **Azure OpenAI**: `https://your-resource.openai.azure.com` -- **Anthropic Claude**: `https://api.anthropic.com` (with compatible endpoints) -- **Third-party Providers**: Any service implementing OpenAI API format +### Method 3: Cluster Deployment -### Environment Variables +Cluster deployment requires all nodes to connect to the same MySQL and Redis, with Redis being mandatory. It's recommended to use unified distributed MySQL and Redis clusters. -Copy the example configuration file and modify as needed: +**Deployment Requirements:** -```bash -cp .env.example .env -``` +- All nodes must configure identical `AUTH_KEY`, `DATABASE_DSN`, `REDIS_DSN` +- Leader-follower architecture where follower nodes must configure environment variable: `IS_SLAVE=true` -### Key Configuration Options +For details, please refer to [Cluster Deployment Documentation](https://www.gpt-load.com/docs/cluster) -| Setting | Environment Variable | Default | Description | -| ----------------------- | ---------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------- | -| Server Port | `PORT` | 3000 | Server listening port | -| Server Host | `HOST` | 0.0.0.0 | Server binding address | -| Keys File | `KEYS_FILE` | keys.txt | API keys file path | -| Start Index | `START_INDEX` | 0 | Starting key index for rotation | -| Blacklist Threshold | `BLACKLIST_THRESHOLD` | 1 | Error count before blacklisting | -| Max Retries | `MAX_RETRIES` | 3 | Maximum retry attempts with different keys | -| Upstream URL | `OPENAI_BASE_URL` | `https://api.openai.com` | OpenAI-compatible API base URL. Supports multiple, comma-separated URLs for load balancing. | -| Max Concurrent Requests | `MAX_CONCURRENT_REQUESTS` | 100 | Maximum number of concurrent requests | -| Enable Gzip | `ENABLE_GZIP` | true | Enable Gzip compression for responses | -| Auth Key | `AUTH_KEY` | - | Optional authentication key | -| CORS | `ENABLE_CORS` | true | Enable CORS support | -| Allowed Origins | `ALLOWED_ORIGINS` | \* | CORS allowed origins (comma-separated, \* for all) | -| Allowed Methods | `ALLOWED_METHODS` | GET,POST,PUT,DELETE,OPTIONS | CORS allowed HTTP methods | -| Allowed Headers | `ALLOWED_HEADERS` | \* | CORS allowed headers (comma-separated, \* for all) | -| Allow Credentials | `ALLOW_CREDENTIALS` | false | CORS allow credentials | -| Log Level | `LOG_LEVEL` | info | Logging level (debug, info, warn, error) | -| Log Format | `LOG_FORMAT` | text | Log format (text, json) | -| Enable File Logging | `LOG_ENABLE_FILE` | false | Enable logging to file | -| Log File Path | `LOG_FILE_PATH` | logs/app.log | Log file path | -| Enable Request Logging | `LOG_ENABLE_REQUEST` | true | Enable request logging (set to false in production for performance) | -| Server Read Timeout | `SERVER_READ_TIMEOUT` | 120 | HTTP server read timeout in seconds | -| Server Write Timeout | `SERVER_WRITE_TIMEOUT` | 1800 | HTTP server write timeout in seconds | -| Server Idle Timeout | `SERVER_IDLE_TIMEOUT` | 120 | HTTP server idle timeout in seconds | -| Graceful Shutdown | `SERVER_GRACEFUL_SHUTDOWN_TIMEOUT` | 60 | Graceful shutdown timeout in seconds | -| Request Timeout | `REQUEST_TIMEOUT` | 30 | Request timeout in seconds | -| Response Timeout | `RESPONSE_TIMEOUT` | 30 | Response timeout in seconds (TLS handshake & response header) | -| Idle Connection Timeout | `IDLE_CONN_TIMEOUT` | 120 | Idle connection timeout in seconds | +## Configuration System -### Configuration Examples +### Configuration Architecture Overview -#### OpenAI (Default) +GPT-Load adopts a dual-layer configuration architecture: -```bash -OPENAI_BASE_URL=https://api.openai.com -# Use OpenAI API keys: sk-... -``` +#### 1. Static Configuration (Environment Variables) -#### Azure OpenAI +- **Characteristics**: Read at application startup, immutable during runtime, requires application restart to take effect +- **Purpose**: Infrastructure configuration such as database connections, server ports, authentication keys, etc. +- **Management**: Set via `.env` files or system environment variables -```bash -OPENAI_BASE_URL=https://your-resource.openai.azure.com -# Use Azure API keys and adjust endpoints as needed -``` +#### 2. Dynamic Configuration (Hot-Reload) -#### Third-party Provider +- **System Settings**: Stored in database, providing unified behavioral standards for the entire application +- **Group Configuration**: Behavior parameters customized for specific groups, can override system settings +- **Configuration Priority**: Group Configuration > System Settings +- **Characteristics**: Supports hot-reload, takes effect immediately after modification without application restart -```bash -OPENAI_BASE_URL=https://api.your-provider.com -# Use provider-specific API keys -``` +### Static Configuration (Environment Variables) -#### Multi-Target Load Balancing +#### Server Configuration -```bash -# Use a comma-separated list of target URLs -OPENAI_BASE_URL=https://gateway.ai.cloudflare.com/v1/.../openai,https://api.openai.com/v1,https://api.another-provider.com/v1 -``` +| Setting | Environment Variable | Default | Description | +| ------------------------- | ---------------------------------- | --------------- | ----------------------------------------------- | +| Service Port | `PORT` | 3001 | HTTP server listening port | +| Service Address | `HOST` | 0.0.0.0 | HTTP server binding address | +| Read Timeout | `SERVER_READ_TIMEOUT` | 60 | HTTP server read timeout (seconds) | +| Write Timeout | `SERVER_WRITE_TIMEOUT` | 600 | HTTP server write timeout (seconds) | +| Idle Timeout | `SERVER_IDLE_TIMEOUT` | 120 | HTTP connection idle timeout (seconds) | +| Graceful Shutdown Timeout | `SERVER_GRACEFUL_SHUTDOWN_TIMEOUT` | 10 | Service graceful shutdown wait time (seconds) | +| Follower Mode | `IS_SLAVE` | false | Follower node identifier for cluster deployment | +| Timezone | `TZ` | `Asia/Shanghai` | Specify timezone | -## API Key Validation +#### Authentication & Database Configuration -The project includes a high-performance API key validation tool: +| Setting | Environment Variable | Default | Description | +| ------------------- | -------------------- | ----------- | ------------------------------------------------------------------------------- | +| Authentication Key | `AUTH_KEY` | `sk-123456` | Unique authentication key for accessing management interface and proxy requests | +| Database Connection | `DATABASE_DSN` | - | MySQL database connection string | +| Redis Connection | `REDIS_DSN` | - | Redis connection string, uses memory storage when empty | -```bash -# Validate keys automatically -make validate-keys +#### Performance & CORS Configuration -# Or run directly -./scripts/validate-keys.py -``` +| Setting | Environment Variable | Default | Description | +| ----------------------- | ------------------------- | ----------------------------- | ----------------------------------------------- | +| Max Concurrent Requests | `MAX_CONCURRENT_REQUESTS` | 100 | Maximum concurrent requests allowed by system | +| Enable CORS | `ENABLE_CORS` | true | Whether to enable Cross-Origin Resource Sharing | +| Allowed Origins | `ALLOWED_ORIGINS` | `*` | Allowed origins, comma-separated | +| Allowed Methods | `ALLOWED_METHODS` | `GET,POST,PUT,DELETE,OPTIONS` | Allowed HTTP methods | +| Allowed Headers | `ALLOWED_HEADERS` | `*` | Allowed request headers, comma-separated | +| Allow Credentials | `ALLOW_CREDENTIALS` | false | Whether to allow sending credentials | -## Monitoring Endpoints +#### Logging Configuration -| Endpoint | Method | Description | -| ------------- | ------ | ----------------------------- | -| `/health` | GET | Health check and basic status | -| `/stats` | GET | Detailed statistics | -| `/blacklist` | GET | Blacklist information | -| `/reset-keys` | GET | Reset all key states | +| Setting | Environment Variable | Default | Description | +| ------------------- | -------------------- | -------------- | ----------------------------------- | +| Log Level | `LOG_LEVEL` | `info` | Log level: debug, info, warn, error | +| Log Format | `LOG_FORMAT` | `text` | Log format: text, json | +| Enable File Logging | `LOG_ENABLE_FILE` | false | Whether to enable file log output | +| Log File Path | `LOG_FILE_PATH` | `logs/app.log` | Log file storage path | -## Development +### Dynamic Configuration (Hot-Reload) -### Available Commands +Dynamic configuration is stored in the database and supports real-time modification through the web management interface, taking effect immediately without restart. -```bash -# Build -make build # Build binary -make build-all # Build for all platforms -make clean # Clean build files +**Configuration Priority**: Group Configuration > System Settings -# Run -make run # Run server -make dev # Development mode with race detection +#### Basic Settings -# Test -make test # Run tests -make coverage # Generate coverage report -make bench # Run benchmarks +| Setting | Field Name | Default | Group Override | Description | +| ------------------ | ------------------------------------ | ----------------------- | -------------- | -------------------------------------------- | +| Project URL | `app_url` | `http://localhost:3001` | ❌ | Project base URL | +| Log Retention Days | `request_log_retention_days` | 7 | ❌ | Request log retention days, 0 for no cleanup | +| Log Write Interval | `request_log_write_interval_minutes` | 5 | ❌ | Log write to database cycle (minutes) | -# Code Quality -make lint # Code linting -make fmt # Format code -make tidy # Tidy dependencies +#### Request Settings -# Management -make health # Health check -make stats # View statistics -make reset-keys # Reset key states -make blacklist # View blacklist +| Setting | Field Name | Default | Group Override | Description | +| ----------------------------- | ------------------------- | ------- | -------------- | ------------------------------------------------------------------- | +| Request Timeout | `request_timeout` | 600 | ✅ | Forward request complete lifecycle timeout (seconds) | +| Connection Timeout | `connect_timeout` | 15 | ✅ | Timeout for establishing connection with upstream service (seconds) | +| Idle Connection Timeout | `idle_conn_timeout` | 120 | ✅ | HTTP client idle connection timeout (seconds) | +| Response Header Timeout | `response_header_timeout` | 15 | ✅ | Timeout for waiting upstream response headers (seconds) | +| Max Idle Connections | `max_idle_conns` | 100 | ✅ | Connection pool maximum total idle connections | +| Max Idle Connections Per Host | `max_idle_conns_per_host` | 50 | ✅ | Maximum idle connections per upstream host | -# Help -make help # Show all commands -``` +#### Key Configuration -### Project Structure +| Setting | Field Name | Default | Group Override | Description | +| -------------------------- | --------------------------------- | ------- | -------------- | -------------------------------------------------------------------------- | +| Max Retries | `max_retries` | 3 | ✅ | Maximum retry count using different keys for single request | +| Blacklist Threshold | `blacklist_threshold` | 3 | ✅ | Number of consecutive failures before key enters blacklist | +| Key Validation Interval | `key_validation_interval_minutes` | 60 | ✅ | Background scheduled key validation cycle (minutes) | +| Key Validation Concurrency | `key_validation_concurrency` | 10 | ✅ | Concurrency for background validation of invalid keys | +| Key Validation Timeout | `key_validation_timeout_seconds` | 20 | ✅ | API request timeout for validating individual keys in background (seconds) | + +## Web Management Interface + +Access the management console at: (default address) + +The web management interface provides the following features: + +- **Dashboard**: Real-time statistics and system status overview +- **Key Management**: Create and configure AI service provider groups, add, delete, and monitor API keys +- **Request Logs**: Detailed request history and debugging information +- **System Settings**: Global configuration management and hot-reload + +## API Usage Guide + +### Proxy Interface Invocation + +GPT-Load routes requests to different AI services through group names. Usage is as follows: + +#### 1. Proxy Endpoint Format ```text -/ -├── cmd/ -│ └── gpt-load/ -│ └── main.go # Main entry point -├── internal/ -│ ├── config/ -│ │ └── manager.go # Configuration management -│ ├── errors/ -│ │ └── errors.go # Custom error types -│ ├── handler/ -│ │ └── handler.go # HTTP handlers -│ ├── keymanager/ -│ │ └── manager.go # Key manager -│ ├── middleware/ -│ │ └── middleware.go # HTTP middleware -│ └── proxy/ -│ └── 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 +http://localhost:3001/proxy/{group_name}/{original_api_path} ``` -## Architecture +- `{group_name}`: Group name created in the management interface +- `{original_api_path}`: Maintain complete consistency with original AI service paths -### Performance Features +#### 2. Authentication Methods -- **Concurrent Processing**: Leverages Go's goroutines for high concurrency -- **Memory Efficiency**: Zero-copy streaming with minimal memory allocation -- **Connection Pooling**: HTTP/2 support with optimized connection reuse -- **Atomic Operations**: Lock-free concurrent operations -- **Pre-compiled Patterns**: Regex patterns compiled at startup +As a transparent proxy service, GPT-Load completely preserves the native authentication formats of various AI services: -### Security & Reliability +- **OpenAI Format**: Uses `Authorization: Bearer {AUTH_KEY}` header authentication +- **Gemini Format**: Uses URL parameter `key={AUTH_KEY}` authentication +- **Unified Key**: All services use the unified key value configured in the `AUTH_KEY` environment variable -- **Memory Safety**: Go's built-in memory safety prevents buffer overflows -- **Concurrent Safety**: Uses sync.Map and atomic operations for thread safety -- **Error Handling**: Comprehensive error handling and recovery mechanisms -- **Resource Management**: Automatic cleanup prevents resource leaks +#### 3. OpenAI Interface Example -## Sponsor +Assuming a group named `openai` was created: - +**Original invocation:** -CDN acceleration and security protection for this project are sponsored by Tencent EdgeOne. +```bash +curl -X POST https://api.openai.com/v1/chat/completions \ + -H "Authorization: Bearer sk-your-openai-key" \ + -H "Content-Type: application/json" \ + -d '{"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Hello"}]}' +``` -## 🌟 Star History +**Proxy invocation:** -[![Stargazers over time](https://starchart.cc/tbphp/gpt-load.svg?variant=adaptive)](https://starchart.cc/tbphp/gpt-load) +```bash +curl -X POST http://localhost:3001/proxy/openai/v1/chat/completions \ + -H "Authorization: Bearer sk-123456" \ + -H "Content-Type: application/json" \ + -d '{"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Hello"}]}' +``` + +**Changes required:** + +- Replace `https://api.openai.com` with `http://localhost:3001/proxy/openai` +- Replace original API Key with unified authentication key `sk-123456` (default value) + +#### 4. Gemini Interface Example + +Assuming a group named `gemini` was created: + +**Original invocation:** + +```bash +curl -X POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent?key=your-gemini-key \ + -H "Content-Type: application/json" \ + -d '{"contents": [{"parts": [{"text": "Hello"}]}]}' +``` + +**Proxy invocation:** + +```bash +curl -X POST http://localhost:3001/proxy/gemini/v1beta/models/gemini-2.5-pro:generateContent?key=sk-123456 \ + -H "Content-Type: application/json" \ + -d '{"contents": [{"parts": [{"text": "Hello"}]}]}' +``` + +**Changes required:** + +- Replace `https://generativelanguage.googleapis.com` with `http://localhost:3001/proxy/gemini` +- Replace `key=your-gemini-key` in URL parameter with unified authentication key `sk-123456` (default value) + +#### 5. Supported Interfaces + +**OpenAI Format:** + +- `/v1/chat/completions` - Chat conversations +- `/v1/completions` - Text completion +- `/v1/embeddings` - Text embeddings +- `/v1/models` - Model list +- And all other OpenAI-compatible interfaces + +**Gemini Format:** + +- `/v1beta/models/*/generateContent` - Content generation +- `/v1beta/models` - Model list +- And all other Gemini native interfaces + +#### 6. Client SDK Configuration + +**OpenAI Python SDK:** + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-123456", # Use unified authentication key + base_url="http://localhost:3001/proxy/openai" # Use proxy endpoint +) + +response = client.chat.completions.create( + model="gpt-4.1-mini", + messages=[{"role": "user", "content": "Hello"}] +) +``` + +**Google Gemini SDK (Python):** + +```python +import google.generativeai as genai + +# Configure API key and base URL +genai.configure( + api_key="sk-123456", # Use unified authentication key + client_options={"api_endpoint": "http://localhost:3001/proxy/gemini"} +) + +model = genai.GenerativeModel('gemini-2.5-pro') +response = model.generate_content("Hello") +``` + +> **Important Note**: As a transparent proxy service, GPT-Load completely preserves the native API formats and authentication methods of various AI services. You only need to replace the endpoint address and use the unified key value for seamless migration. ## License MIT License - see [LICENSE](LICENSE) file for details. + +## Star History + +[![Stargazers over time](https://starchart.cc/tbphp/gpt-load.svg?variant=adaptive)](https://starchart.cc/tbphp/gpt-load) diff --git a/README_CN.md b/README_CN.md index f588d41..0daaee5 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,60 +2,79 @@ 中文文档 | [English](README.md) -![Docker Build](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml/badge.svg) -![Go Version](https://img.shields.io/badge/Go-1.21+-blue.svg) +[![Release](https://img.shields.io/github/v/release/tbphp/gpt-load)](https://github.com/tbphp/gpt-load/releases) +[![Build Docker Image](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml/badge.svg)](https://github.com/tbphp/gpt-load/actions/workflows/docker-build.yml) +![Go Version](https://img.shields.io/badge/Go-1.23+-blue.svg) ![License](https://img.shields.io/badge/license-MIT-green.svg) -一个高性能的 OpenAI 兼容 API 多密钥轮询代理服务器,支持负载均衡,使用 Go 语言开发。 +一个高性能、企业级的 AI 接口透明代理服务,专门为需要集成多种 AI 服务的企业和开发者设计。采用 Go 语言开发,具备智能密钥管理、负载均衡和完善的监控功能,专为高并发生产环境而设计。 + +详细请查看[官方文档](https://www.gpt-load.com/docs) ## 功能特性 -- **多密钥轮询**: 自动 API 密钥轮换和负载均衡 -- **多目标负载均衡**: 支持轮询多个上游 API 地址 -- **智能拉黑**: 区分永久性和临时性错误,智能密钥管理 -- **实时监控**: 全面的统计信息、健康检查和黑名单管理 -- **灵活配置**: 基于环境变量的配置,支持 .env 文件 -- **CORS 支持**: 完整的跨域请求支持 -- **结构化日志**: 详细的日志记录,包含响应时间和密钥信息 -- **可选认证**: 项目级 Bearer token 认证 -- **高性能**: 零拷贝流式传输、并发处理和原子操作 -- **生产就绪**: 优雅关闭、错误恢复和内存管理 +- **透明代理**: 完全保留原生 API 格式,支持 OpenAI 和 Google Gemini 等多种格式(持续扩展中) +- **智能密钥管理**: 高性能密钥池,支持分组管理、自动轮换和故障恢复 +- **负载均衡**: 支持多上游端点的加权负载均衡,提升服务可用性 +- **智能故障处理**: 自动密钥黑名单管理和恢复机制,确保服务连续性 +- **动态配置**: 系统设置和分组配置支持热重载,无需重启即可生效 +- **企业级架构**: 分布式主从部署,支持水平扩展和高可用 +- **现代化管理**: 基于 Vue 3 的 Web 管理界面,直观易用 +- **全面监控**: 实时统计、健康检查、详细请求日志 +- **高性能设计**: 零拷贝流式传输、连接池复用、原子操作 +- **生产就绪**: 优雅关闭、错误恢复、完善的安全机制 + +## 支持的 AI 服务 + +GPT-Load 作为透明代理服务,完整保留各 AI 服务商的原生 API 格式: + +- **OpenAI 格式**: 官方 OpenAI API、Azure OpenAI、以及其他 OpenAI 兼容服务 +- **Google Gemini 格式**: Gemini Pro、Gemini Pro Vision 等模型的原生 API +- **扩展性**: 插件化架构设计,可快速集成新的 AI 服务提供商及其原生格式 ## 快速开始 ### 环境要求 -- Go 1.21+ (源码构建) +- Go 1.23+ (源码构建) - Docker (容器化部署) +- MySQL 8.2+ (数据库存储) +- Redis (缓存和分布式协调,可选) -### 方式一:使用 Docker(推荐) +### 方式一:使用 Docker Compose(推荐) ```bash -# 拉取最新镜像 -docker pull ghcr.io/tbphp/gpt-load:latest +# 下载配置文件 +wget https://raw.githubusercontent.com/tbphp/gpt-load/refs/heads/main/docker-compose.yml +wget -O .env https://raw.githubusercontent.com/tbphp/gpt-load/refs/heads/main/.env.example -# 创建密钥文件,每行一个 API 密钥 -echo "sk-your-api-key-1" > keys.txt -echo "sk-your-api-key-2" >> keys.txt +# 编辑配置文件(根据需要修改服务端口和认证Key等) +vim .env -# 运行容器 -docker run -d -p 3000:3000 \ - -v $(pwd)/keys.txt:/app/keys.txt:ro \ - --name gpt-load \ - ghcr.io/tbphp/gpt-load:latest +# 启动服务(包含 MySQL 和 Redis) +docker compose up -d + +# 查看服务状态 +docker compose ps + +# 查看日志 +docker compose logs -f gpt-load + +# 常用操作 +docker compose restart gpt-load # 重启服务 +docker compose pull && docker compose down && docker compose up -d # 更新到最新版本 ``` -### 方式二:使用 Docker Compose +部署完成后: -```bash -# 启动服务 -docker-compose up -d +- 访问 Web 管理界面: +- API 代理地址: -# 停止服务 -docker-compose down -``` +> 使用默认的认证 Key `sk-123456` 登录管理端,认证 Key 可以在 .env 中修改 AUTH_KEY。 -### 方式三:源码构建 +### 方式二:源码构建 + +源码构建需要本地已安装 MySQL 和 Redis(可选)。 ```bash # 克隆并构建 @@ -65,207 +84,270 @@ go mod tidy # 创建配置 cp .env.example .env -echo "sk-your-api-key" > keys.txt + +# 修改 .env 中 DATABASE_DSN 和 REDIS_DSN 配置 +# REDIS_DSN 为可选,如果不配置则启用内存存储 # 运行 make run ``` -## 配置说明 +部署完成后: -### 支持的 API 提供商 +- 访问 Web 管理界面: +- API 代理地址: -此代理服务器支持任何 OpenAI 兼容的 API,包括: +> 使用默认的认证 Key `sk-123456` 登录管理端,认证 Key 可以在 .env 中修改 AUTH_KEY。 -- **OpenAI**: `https://api.openai.com` -- **Azure OpenAI**: `https://your-resource.openai.azure.com` -- **Anthropic Claude**: `https://api.anthropic.com` (兼容端点) -- **第三方提供商**: 任何实现 OpenAI API 格式的服务 +### 方式三:集群部署 -### 环境变量 +集群部署需要所有节点都连接同一个 MySQL 和 Redis,并且 Redis 是必须要求。建议使用统一的分布式 MySQL 和 Redis 集群。 -复制示例配置文件并根据需要修改: +**部署要求:** -```bash -cp .env.example .env -``` +- 所有节点必须配置相同的 `AUTH_KEY`、`DATABASE_DSN`、`REDIS_DSN` +- 一主多从架构,从节点必须配置环境变量:`IS_SLAVE=true` -### 主要配置选项 +详细请参考[集群部署文档](https://www.gpt-load.com/docs/cluster) -| 配置项 | 环境变量 | 默认值 | 说明 | -| -------------- | ---------------------------------- | --------------------------- | -------------------------------------------------- | -| 服务器端口 | `PORT` | 3000 | 服务器监听端口 | -| 服务器主机 | `HOST` | 0.0.0.0 | 服务器绑定地址 | -| 密钥文件 | `KEYS_FILE` | keys.txt | API 密钥文件路径 | -| 起始索引 | `START_INDEX` | 0 | 密钥轮换起始索引 | -| 拉黑阈值 | `BLACKLIST_THRESHOLD` | 1 | 拉黑前的错误次数 | -| 最大重试次数 | `MAX_RETRIES` | 3 | 使用不同密钥的最大重试次数 | -| 上游地址 | `OPENAI_BASE_URL` | `https://api.openai.com` | OpenAI 兼容 API 基础地址。支持多个地址,用逗号分隔 | -| 最大并发请求数 | `MAX_CONCURRENT_REQUESTS` | 100 | 最大并发请求数 | -| 启用 Gzip 压缩 | `ENABLE_GZIP` | true | 启用响应 Gzip 压缩 | -| 认证密钥 | `AUTH_KEY` | - | 可选的认证密钥 | -| 启用 CORS | `ENABLE_CORS` | true | 启用 CORS 支持 | -| 允许的来源 | `ALLOWED_ORIGINS` | \* | CORS 允许的来源(逗号分隔,\* 表示允许所有) | -| 允许的方法 | `ALLOWED_METHODS` | GET,POST,PUT,DELETE,OPTIONS | CORS 允许的 HTTP 方法 | -| 允许的头部 | `ALLOWED_HEADERS` | \* | CORS 允许的头部(逗号分隔,\* 表示允许所有) | -| 允许凭证 | `ALLOW_CREDENTIALS` | false | CORS 允许凭证 | -| 日志级别 | `LOG_LEVEL` | info | 日志级别(debug, info, warn, error) | -| 日志格式 | `LOG_FORMAT` | text | 日志格式(text, json) | -| 启用文件日志 | `LOG_ENABLE_FILE` | false | 启用文件日志 | -| 日志文件路径 | `LOG_FILE_PATH` | logs/app.log | 日志文件路径 | -| 启用请求日志 | `LOG_ENABLE_REQUEST` | true | 启用请求日志(生产环境可设为 false 以提高性能) | -| 服务器读取超时 | `SERVER_READ_TIMEOUT` | 120 | HTTP 服务器读取超时时间(秒) | -| 服务器写入超时 | `SERVER_WRITE_TIMEOUT` | 1800 | HTTP 服务器写入超时时间(秒) | -| 服务器空闲超时 | `SERVER_IDLE_TIMEOUT` | 120 | HTTP 服务器空闲超时时间(秒) | -| 优雅关闭超时 | `SERVER_GRACEFUL_SHUTDOWN_TIMEOUT` | 60 | 服务器优雅关闭超时时间(秒) | -| 请求超时 | `REQUEST_TIMEOUT` | 30 | 请求超时时间(秒) | -| 响应超时 | `RESPONSE_TIMEOUT` | 30 | 响应超时时间(秒)- 控制 TLS 握手和响应头接收 | -| 空闲连接超时 | `IDLE_CONN_TIMEOUT` | 120 | 空闲连接超时时间(秒) | +## 配置系统 -### 配置示例 +### 配置架构概述 -#### OpenAI(默认) +GPT-Load 采用双层配置架构: -```bash -OPENAI_BASE_URL=https://api.openai.com -# 使用 OpenAI API 密钥: sk-... -``` +#### 1. 静态配置(环境变量) -#### Azure OpenAI +- **特点**:应用启动时读取,运行期间不可修改,需重启应用生效 +- **用途**:基础设施配置,如数据库连接、服务器端口、认证密钥等 +- **管理方式**:通过 `.env` 文件或系统环境变量设置 -```bash -OPENAI_BASE_URL=https://your-resource.openai.azure.com -# 使用 Azure API 密钥,根据需要调整端点 -``` +#### 2. 动态配置(热重载) -#### 第三方提供商 +- **系统设置**:存储在数据库中,为整个应用提供统一的行为基准 +- **分组配置**:为特定分组定制的行为参数,可覆盖系统设置 +- **配置优先级**:分组配置 > 系统设置 +- **特点**:支持热重载,修改后立即生效,无需重启应用 -```bash -OPENAI_BASE_URL=https://api.your-provider.com -# 使用提供商特定的 API 密钥 -``` +### 静态配置(环境变量) -#### 多目标负载均衡 +#### 服务器配置 -```bash -# 使用逗号分隔多个目标地址 -OPENAI_BASE_URL=https://gateway.ai.cloudflare.com/v1/.../openai,https://api.openai.com/v1,https://api.another-provider.com/v1 -``` +| 配置项 | 环境变量 | 默认值 | 说明 | +| ------------ | ---------------------------------- | --------------- | -------------------------- | +| 服务端口 | `PORT` | 3001 | HTTP 服务器监听端口 | +| 服务地址 | `HOST` | 0.0.0.0 | HTTP 服务器绑定地址 | +| 读取超时 | `SERVER_READ_TIMEOUT` | 60 | HTTP 服务器读取超时(秒) | +| 写入超时 | `SERVER_WRITE_TIMEOUT` | 600 | HTTP 服务器写入超时(秒) | +| 空闲超时 | `SERVER_IDLE_TIMEOUT` | 120 | HTTP 连接空闲超时(秒) | +| 优雅关闭超时 | `SERVER_GRACEFUL_SHUTDOWN_TIMEOUT` | 10 | 服务优雅关闭等待时间(秒) | +| 从节点模式 | `IS_SLAVE` | false | 集群部署时从节点标识 | +| 时区 | `TZ` | `Asia/Shanghai` | 指定时区 | -## API 密钥验证 +#### 认证与数据库配置 -项目包含高性能的 API 密钥验证工具: +| 配置项 | 环境变量 | 默认值 | 说明 | +| ---------- | -------------- | ----------- | ------------------------------------ | +| 认证密钥 | `AUTH_KEY` | `sk-123456` | 访问管理端以及请求代理的唯一认证密钥 | +| 数据库连接 | `DATABASE_DSN` | - | MySQL 数据库连接字符串 | +| Redis 连接 | `REDIS_DSN` | - | Redis 连接字符串,为空时使用内存存储 | -```bash -# 自动验证密钥 -make validate-keys +#### 性能与跨域配置 -# 或直接运行 -./scripts/validate-keys.py -``` +| 配置项 | 环境变量 | 默认值 | 说明 | +| ------------ | ------------------------- | ----------------------------- | ------------------------ | +| 最大并发请求 | `MAX_CONCURRENT_REQUESTS` | 100 | 系统允许的最大并发请求数 | +| 启用 CORS | `ENABLE_CORS` | true | 是否启用跨域资源共享 | +| 允许的来源 | `ALLOWED_ORIGINS` | `*` | 允许的来源,逗号分隔 | +| 允许的方法 | `ALLOWED_METHODS` | `GET,POST,PUT,DELETE,OPTIONS` | 允许的 HTTP 方法 | +| 允许的头部 | `ALLOWED_HEADERS` | `*` | 允许的请求头,逗号分隔 | +| 允许凭据 | `ALLOW_CREDENTIALS` | false | 是否允许发送凭据 | -## 监控端点 +#### 日志配置 -| 端点 | 方法 | 说明 | -| ------------- | ---- | ------------------ | -| `/health` | GET | 健康检查和基本状态 | -| `/stats` | GET | 详细统计信息 | -| `/blacklist` | GET | 黑名单信息 | -| `/reset-keys` | GET | 重置所有密钥状态 | +| 配置项 | 环境变量 | 默认值 | 说明 | +| ------------ | ----------------- | -------------- | ---------------------------------- | +| 日志级别 | `LOG_LEVEL` | `info` | 日志级别:debug, info, warn, error | +| 日志格式 | `LOG_FORMAT` | `text` | 日志格式:text, json | +| 启用文件日志 | `LOG_ENABLE_FILE` | false | 是否启用文件日志输出 | +| 日志文件路径 | `LOG_FILE_PATH` | `logs/app.log` | 日志文件存储路径 | -## 开发 +### 动态配置(热重载) -### 可用命令 +动态配置存储在数据库中,支持通过 Web 管理界面进行实时修改,修改后立即生效无需重启。 -```bash -# 构建 -make build # 构建二进制文件 -make build-all # 构建所有平台版本 -make clean # 清理构建文件 +**配置优先级**:分组配置 > 系统设置 -# 运行 -make run # 运行服务器 -make dev # 开发模式(启用竞态检测) +#### 基础设置 -# 测试 -make test # 运行测试 -make coverage # 生成覆盖率报告 -make bench # 运行基准测试 +| 配置项 | 字段名 | 默认值 | 分组可覆盖 | 说明 | +| ------------ | ------------------------------------ | ----------------------- | ---------- | ---------------------------- | +| 项目地址 | `app_url` | `http://localhost:3001` | ❌ | 项目基础 URL | +| 日志保留天数 | `request_log_retention_days` | 7 | ❌ | 请求日志保留天数,0 为不清理 | +| 日志写入间隔 | `request_log_write_interval_minutes` | 5 | ❌ | 日志写入数据库周期(分钟) | -# 代码质量 -make lint # 代码检查 -make fmt # 格式化代码 -make tidy # 整理依赖 +#### 请求设置 -# 管理 -make health # 健康检查 -make stats # 查看统计信息 -make reset-keys # 重置密钥状态 -make blacklist # 查看黑名单 +| 配置项 | 字段名 | 默认值 | 分组可覆盖 | 说明 | +| -------------------- | ------------------------- | ------ | ---------- | ------------------------------ | +| 请求超时 | `request_timeout` | 600 | ✅ | 转发请求完整生命周期超时(秒) | +| 连接超时 | `connect_timeout` | 15 | ✅ | 与上游服务建立连接超时(秒) | +| 空闲连接超时 | `idle_conn_timeout` | 120 | ✅ | HTTP 客户端空闲连接超时(秒) | +| 响应头超时 | `response_header_timeout` | 15 | ✅ | 等待上游响应头超时(秒) | +| 最大空闲连接数 | `max_idle_conns` | 100 | ✅ | 连接池最大空闲连接总数 | +| 每主机最大空闲连接数 | `max_idle_conns_per_host` | 50 | ✅ | 每个上游主机最大空闲连接数 | -# 帮助 -make help # 显示所有命令 -``` +#### 密钥配置 -### 项目结构 +| 配置项 | 字段名 | 默认值 | 分组可覆盖 | 说明 | +| -------------- | --------------------------------- | ------ | ---------- | ------------------------------------------------ | +| 最大重试次数 | `max_retries` | 3 | ✅ | 单个请求使用不同密钥的最大重试次数 | +| 黑名单阈值 | `blacklist_threshold` | 3 | ✅ | 密钥连续失败多少次后进入黑名单 | +| 密钥验证间隔 | `key_validation_interval_minutes` | 60 | ✅ | 后台定时验证密钥周期(分钟) | +| 密钥验证并发数 | `key_validation_concurrency` | 10 | ✅ | 后台定时验证无效 Key 时的并发数 | +| 密钥验证超时 | `key_validation_timeout_seconds` | 20 | ✅ | 后台定时验证单个 Key 时的 API 请求超时时间(秒) | + +## Web 管理界面 + +访问管理控制台:(默认地址) + +Web 管理界面提供以下功能: + +- **仪表盘**: 实时统计信息和系统状态概览 +- **密钥管理**: 创建和配置 AI 服务商分组,添加、删除和监控 API 密钥 +- **请求日志**: 详细的请求历史记录和调试信息 +- **系统设置**: 全局配置管理和热重载 + +## API 使用说明 + +### 代理接口调用方式 + +GPT-Load 通过分组名称路由请求到不同的 AI 服务。使用方式如下: + +#### 1. 代理端点格式 ```text -/ -├── cmd/ -│ └── gpt-load/ -│ └── main.go # 主入口文件 -├── internal/ -│ ├── config/ -│ │ └── manager.go # 配置管理 -│ ├── errors/ -│ │ └── errors.go # 自定义错误类型 -│ ├── handler/ -│ │ └── handler.go # HTTP 处理器 -│ ├── keymanager/ -│ │ └── manager.go # 密钥管理器 -│ ├── middleware/ -│ │ └── middleware.go # HTTP 中间件 -│ └── proxy/ -│ └── 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 # 项目文档 +http://localhost:3001/proxy/{group_name}/{原始API路径} ``` -## 架构 +- `{group_name}`: 在管理界面创建的分组名称 +- `{原始API路径}`: 保持与原始 AI 服务完全一致的路径 -### 性能特性 +#### 2. 认证方式 -- **并发处理**: 利用 Go 的 goroutine 实现高并发 -- **内存效率**: 零拷贝流式传输,最小化内存分配 -- **连接池**: HTTP/2 支持,优化连接复用 -- **原子操作**: 无锁并发操作 -- **预编译模式**: 启动时编译正则表达式模式 +作为透明代理服务,GPT-Load 完全保留各 AI 服务的原生认证格式: -### 安全性与可靠性 +- **OpenAI 格式**: 使用 `Authorization: Bearer {AUTH_KEY}` 头部认证 +- **Gemini 格式**: 使用 URL 参数 `key={AUTH_KEY}` 认证 +- **统一密钥**: 所有服务都使用环境变量 `AUTH_KEY` 中配置的统一密钥值 -- **内存安全**: Go 的内置内存安全防止缓冲区溢出 -- **并发安全**: 使用 sync.Map 和原子操作保证线程安全 -- **错误处理**: 全面的错误处理和恢复机制 -- **资源管理**: 自动清理防止资源泄漏 +#### 3. OpenAI 接口调用示例 -## 🌟 Star History +假设创建了名为 `openai` 的分组: -[![Stargazers over time](https://starchart.cc/tbphp/gpt-load.svg?variant=adaptive)](https://starchart.cc/tbphp/gpt-load) +**原始调用方式:** + +```bash +curl -X POST https://api.openai.com/v1/chat/completions \ + -H "Authorization: Bearer sk-your-openai-key" \ + -H "Content-Type: application/json" \ + -d '{"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Hello"}]}' +``` + +**代理调用方式:** + +```bash +curl -X POST http://localhost:3001/proxy/openai/v1/chat/completions \ + -H "Authorization: Bearer sk-123456" \ + -H "Content-Type: application/json" \ + -d '{"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Hello"}]}' +``` + +**变更说明:** + +- 将 `https://api.openai.com` 替换为 `http://localhost:3001/proxy/openai` +- 将原始 API Key 替换为统一认证密钥 `sk-123456`(默认值) + +#### 4. Gemini 接口调用示例 + +假设创建了名为 `gemini` 的分组: + +**原始调用方式:** + +```bash +curl -X POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent?key=your-gemini-key \ + -H "Content-Type: application/json" \ + -d '{"contents": [{"parts": [{"text": "Hello"}]}]}' +``` + +**代理调用方式:** + +```bash +curl -X POST http://localhost:3001/proxy/gemini/v1beta/models/gemini-2.5-pro:generateContent?key=sk-123456 \ + -H "Content-Type: application/json" \ + -d '{"contents": [{"parts": [{"text": "Hello"}]}]}' +``` + +**变更说明:** + +- 将 `https://generativelanguage.googleapis.com` 替换为 `http://localhost:3001/proxy/gemini` +- 将 URL 参数中的 `key=your-gemini-key` 替换为统一认证密钥 `sk-123456`(默认值) + +#### 5. 支持的接口 + +**OpenAI 格式:** + +- `/v1/chat/completions` - 聊天对话 +- `/v1/completions` - 文本补全 +- `/v1/embeddings` - 文本嵌入 +- `/v1/models` - 模型列表 +- 以及其他所有 OpenAI 兼容接口 + +**Gemini 格式:** + +- `/v1beta/models/*/generateContent` - 内容生成 +- `/v1beta/models` - 模型列表 +- 以及其他所有 Gemini 原生接口 + +#### 6. 客户端 SDK 配置 + +**OpenAI Python SDK:** + +```python +from openai import OpenAI + +client = OpenAI( + api_key="sk-123456", # 使用统一认证密钥 + base_url="http://localhost:3001/proxy/openai" # 使用代理端点 +) + +response = client.chat.completions.create( + model="gpt-4.1-mini", + messages=[{"role": "user", "content": "Hello"}] +) +``` + +**Google Gemini SDK (Python):** + +```python +import google.generativeai as genai + +# 配置 API 密钥和基础 URL +genai.configure( + api_key="sk-123456", # 使用统一认证密钥 + client_options={"api_endpoint": "http://localhost:3001/proxy/gemini"} +) + +model = genai.GenerativeModel('gemini-2.5-pro') +response = model.generate_content("Hello") +``` + +> **重要提示**:作为透明代理服务,GPT-Load 完全保留各 AI 服务的原生 API 格式和认证方式,仅需要替换端点地址并使用统一密钥值即可无缝迁移。 ## 许可证 MIT 许可证 - 详情请参阅 [LICENSE](LICENSE) 文件。 + +## Star History + +[![Stargazers over time](https://starchart.cc/tbphp/gpt-load.svg?variant=adaptive)](https://starchart.cc/tbphp/gpt-load) diff --git a/internal/config/manager.go b/internal/config/manager.go index 83ce907..05af8e7 100644 --- a/internal/config/manager.go +++ b/internal/config/manager.go @@ -73,10 +73,10 @@ func (m *Manager) ReloadConfig() error { IsMaster: !utils.ParseBoolean(os.Getenv("IS_SLAVE"), false), Port: utils.ParseInteger(os.Getenv("PORT"), 3001), Host: utils.GetEnvOrDefault("HOST", "0.0.0.0"), - ReadTimeout: utils.ParseInteger(os.Getenv("SERVER_READ_TIMEOUT"), 120), - WriteTimeout: utils.ParseInteger(os.Getenv("SERVER_WRITE_TIMEOUT"), 1800), + ReadTimeout: utils.ParseInteger(os.Getenv("SERVER_READ_TIMEOUT"), 60), + WriteTimeout: utils.ParseInteger(os.Getenv("SERVER_WRITE_TIMEOUT"), 600), IdleTimeout: utils.ParseInteger(os.Getenv("SERVER_IDLE_TIMEOUT"), 120), - GracefulShutdownTimeout: utils.ParseInteger(os.Getenv("SERVER_GRACEFUL_SHUTDOWN_TIMEOUT"), 60), + GracefulShutdownTimeout: utils.ParseInteger(os.Getenv("SERVER_GRACEFUL_SHUTDOWN_TIMEOUT"), 10), }, Auth: types.AuthConfig{ Key: os.Getenv("AUTH_KEY"), diff --git a/internal/types/types.go b/internal/types/types.go index 556e5f2..ccee089 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -33,9 +33,9 @@ type SystemSettings struct { // 密钥配置 MaxRetries int `json:"max_retries" default:"3" name:"最大重试次数" category:"密钥配置" desc:"单个请求使用不同 Key 的最大重试次数,0为不重试。" validate:"min=0"` BlacklistThreshold int `json:"blacklist_threshold" default:"3" name:"黑名单阈值" category:"密钥配置" desc:"一个 Key 连续失败多少次后进入黑名单,0为不拉黑。" validate:"min=0"` - KeyValidationIntervalMinutes int `json:"key_validation_interval_minutes" default:"60" name:"验证间隔(分钟)" category:"密钥配置" desc:"后台验证密钥的默认间隔(分钟)。" validate:"min=30"` - KeyValidationConcurrency int `json:"key_validation_concurrency" default:"10" name:"验证并发数" category:"密钥配置" desc:"后台定时验证无效 Key 时的并发数。" validate:"min=1"` - KeyValidationTimeoutSeconds int `json:"key_validation_timeout_seconds" default:"20" name:"验证超时(秒)" category:"密钥配置" desc:"后台定时验证单个 Key 时的 API 请求超时时间(秒)。" validate:"min=5"` + KeyValidationIntervalMinutes int `json:"key_validation_interval_minutes" default:"60" name:"密钥验证间隔(分钟)" category:"密钥配置" desc:"后台验证密钥的默认间隔(分钟)。" validate:"min=30"` + KeyValidationConcurrency int `json:"key_validation_concurrency" default:"10" name:"密钥验证并发数" category:"密钥配置" desc:"后台定时验证无效 Key 时的并发数。" validate:"min=1"` + KeyValidationTimeoutSeconds int `json:"key_validation_timeout_seconds" default:"20" name:"密钥验证超时(秒)" category:"密钥配置" desc:"后台定时验证单个 Key 时的 API 请求超时时间(秒)。" validate:"min=5"` } // ServerConfig represents server configuration