diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index 91437ba8..01436cd1 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -789,8 +789,8 @@ func setDefaults() { viper.SetDefault("redis.dial_timeout_seconds", 5) viper.SetDefault("redis.read_timeout_seconds", 3) viper.SetDefault("redis.write_timeout_seconds", 3) - viper.SetDefault("redis.pool_size", 128) - viper.SetDefault("redis.min_idle_conns", 10) + viper.SetDefault("redis.pool_size", 1024) + viper.SetDefault("redis.min_idle_conns", 128) viper.SetDefault("redis.enable_tls", false) // Ops (vNext) @@ -888,7 +888,7 @@ func setDefaults() { // HTTP 上游连接池配置(针对 5000+ 并发用户优化) viper.SetDefault("gateway.max_idle_conns", 240) // 最大空闲连接总数(HTTP/2 场景默认) viper.SetDefault("gateway.max_idle_conns_per_host", 120) // 每主机最大空闲连接(HTTP/2 场景默认) - viper.SetDefault("gateway.max_conns_per_host", 240) // 每主机最大连接数(含活跃,HTTP/2 场景默认) + viper.SetDefault("gateway.max_conns_per_host", 4096) // 每主机最大连接数(含活跃;流式/HTTP1.1 可调大) viper.SetDefault("gateway.idle_conn_timeout_seconds", 90) // 空闲连接超时(秒) viper.SetDefault("gateway.max_upstream_clients", 5000) viper.SetDefault("gateway.client_idle_ttl_seconds", 900) diff --git a/backend/internal/service/openai_codex_transform.go b/backend/internal/service/openai_codex_transform.go index d28e13ab..ba3b1b7b 100644 --- a/backend/internal/service/openai_codex_transform.go +++ b/backend/internal/service/openai_codex_transform.go @@ -9,12 +9,29 @@ import ( "os" "path/filepath" "strings" + "sync" "time" ) const ( opencodeCodexHeaderURL = "https://raw.githubusercontent.com/anomalyco/opencode/dev/packages/opencode/src/session/prompt/codex_header.txt" codexCacheTTL = 15 * time.Minute + + // 避免冷启动首请求被外网/ DNS / GitHub 卡死。 + // http.DefaultClient 默认无超时,网络异常时可能阻塞很久。 + opencodeFetchTimeout = 3 * time.Second + // 本地缓存为空时,最小回源间隔(防止并发下反复打 GitHub)。 + opencodeEmptyCacheRefreshInterval = 1 * time.Minute + // 防抖:防止短时间内重复触发异步回源。 + opencodeFetchDebounce = 3 * time.Second +) + +var opencodeFetchHTTPClient = &http.Client{Timeout: opencodeFetchTimeout} + +var ( + opencodeFetchMu sync.Mutex + opencodeFetchInFlight bool + opencodeFetchLastStart time.Time ) //go:embed prompts/codex_cli_instructions.md @@ -230,30 +247,74 @@ func getOpenCodeCachedPrompt(url, cacheFileName, metaFileName string) string { } var meta opencodeCacheMetadata - if loadJSON(metaFile, &meta) && meta.LastChecked > 0 && cachedContent != "" { - if time.Since(time.UnixMilli(meta.LastChecked)) < codexCacheTTL { - return cachedContent + _ = loadJSON(metaFile, &meta) + if meta.LastChecked > 0 { + lastCheckedAt := time.UnixMilli(meta.LastChecked) + if cachedContent != "" { + if time.Since(lastCheckedAt) < codexCacheTTL { + return cachedContent + } + } else { + // 没有任何缓存内容时,回源失败也不应影响请求链路;这里做节流,避免并发下反复回源。 + if time.Since(lastCheckedAt) < opencodeEmptyCacheRefreshInterval { + return "" + } } } - content, etag, status, err := fetchWithETag(url, meta.ETag) - if err == nil && status == http.StatusNotModified && cachedContent != "" { - return cachedContent - } - if err == nil && status >= 200 && status < 300 && content != "" { - _ = writeFile(cacheFile, content) - meta = opencodeCacheMetadata{ - ETag: etag, - LastFetch: time.Now().UTC().Format(time.RFC3339), - LastChecked: time.Now().UnixMilli(), - } - _ = writeJSON(metaFile, meta) - return content - } - + // 不在请求链路内同步拉取(GitHub/DNS/网络异常会导致冷启动首请求卡 1 分钟+)。 + // 直接返回当前缓存(可为空),并异步刷新缓存。 + scheduleOpencodeCacheRefresh(url, cacheFile, metaFile, meta.ETag) return cachedContent } +func scheduleOpencodeCacheRefresh(url, cacheFile, metaFile, etag string) { + opencodeFetchMu.Lock() + if opencodeFetchInFlight { + opencodeFetchMu.Unlock() + return + } + if !opencodeFetchLastStart.IsZero() && time.Since(opencodeFetchLastStart) < opencodeFetchDebounce { + opencodeFetchMu.Unlock() + return + } + opencodeFetchInFlight = true + opencodeFetchLastStart = time.Now() + opencodeFetchMu.Unlock() + + go func() { + defer func() { + opencodeFetchMu.Lock() + opencodeFetchInFlight = false + opencodeFetchMu.Unlock() + }() + + now := time.Now() + content, newETag, status, err := fetchWithETag(url, etag) + + var meta opencodeCacheMetadata + _ = loadJSON(metaFile, &meta) + meta.LastChecked = now.UnixMilli() + + switch { + case err == nil && status == http.StatusNotModified: + // 304 表示无需更新缓存文件,只更新检查时间。 + if newETag != "" { + meta.ETag = newETag + } + _ = writeJSON(metaFile, meta) + case err == nil && status >= 200 && status < 300 && strings.TrimSpace(content) != "": + _ = writeFile(cacheFile, content) + meta.ETag = newETag + meta.LastFetch = now.UTC().Format(time.RFC3339) + _ = writeJSON(metaFile, meta) + default: + // 拉取失败也记录检查时间,避免高并发下持续回源。 + _ = writeJSON(metaFile, meta) + } + }() +} + func getOpenCodeCodexHeader() string { // 优先从 opencode 仓库缓存获取指令。 opencodeInstructions := getOpenCodeCachedPrompt(opencodeCodexHeaderURL, "opencode-codex-header.txt", "opencode-codex-header-meta.json") @@ -598,7 +659,7 @@ func fetchWithETag(url, etag string) (string, string, int, error) { if etag != "" { req.Header.Set("If-None-Match", etag) } - resp, err := http.DefaultClient.Do(req) + resp, err := opencodeFetchHTTPClient.Do(req) if err != nil { return "", "", 0, err } diff --git a/deploy/.env.example b/deploy/.env.example index c5e850ae..17619530 100644 --- a/deploy/.env.example +++ b/deploy/.env.example @@ -59,12 +59,59 @@ POSTGRES_USER=sub2api POSTGRES_PASSWORD=change_this_secure_password POSTGRES_DB=sub2api +# ----------------------------------------------------------------------------- +# PostgreSQL 服务端参数(可选;主要用于 deploy/docker-compose-aicodex.yml) +# ----------------------------------------------------------------------------- +# POSTGRES_MAX_CONNECTIONS:PostgreSQL 服务端允许的最大连接数。 +# 必须 >=(所有 Sub2API 实例的 DATABASE_MAX_OPEN_CONNS 之和)+ 预留余量(例如 20%)。 +POSTGRES_MAX_CONNECTIONS=1024 +# POSTGRES_SHARED_BUFFERS:PostgreSQL 用于缓存数据页的共享内存。 +# 常见建议:物理内存的 10%~25%(容器内存受限时请按实际限制调整)。 +POSTGRES_SHARED_BUFFERS=256MB +# POSTGRES_EFFECTIVE_CACHE_SIZE:查询规划器“假设可用的 OS 缓存大小”(不等于实际分配)。 +# 常见建议:物理内存的 50%~75%。 +POSTGRES_EFFECTIVE_CACHE_SIZE=768MB +# POSTGRES_MAINTENANCE_WORK_MEM:维护操作内存(VACUUM/CREATE INDEX 等)。 +# 值越大维护越快,但会占用更多内存。 +POSTGRES_MAINTENANCE_WORK_MEM=64MB + +# ----------------------------------------------------------------------------- +# PostgreSQL 连接池参数(可选,默认与程序内置一致) +# ----------------------------------------------------------------------------- +# 说明: +# - 这些参数控制 Sub2API 进程到 PostgreSQL 的连接池大小(不是 PostgreSQL 自身的 max_connections)。 +# - 多实例/多副本部署时,总连接上限约等于:实例数 * DATABASE_MAX_OPEN_CONNS。 +# - 连接池过大可能导致:数据库连接耗尽、内存占用上升、上下文切换增多,反而变慢。 +# - 建议结合 PostgreSQL 的 max_connections 与机器规格逐步调优: +# 通常把应用总连接上限控制在 max_connections 的 50%~80% 更稳妥。 +# +# DATABASE_MAX_OPEN_CONNS:最大打开连接数(活跃+空闲),达到后新请求会等待可用连接。 +# 典型范围:50~500(取决于 DB 规格、实例数、SQL 复杂度)。 +DATABASE_MAX_OPEN_CONNS=50 +# DATABASE_MAX_IDLE_CONNS:最大空闲连接数(热连接),建议 <= MAX_OPEN。 +# 太小会频繁建连增加延迟;太大会长期占用数据库资源。 +DATABASE_MAX_IDLE_CONNS=10 +# DATABASE_CONN_MAX_LIFETIME_MINUTES:单个连接最大存活时间。 +# 用于避免连接长期不重建导致的中间件/LB/NAT 异常或服务端重启后的“僵尸连接”。 +# 设置为 0 表示不限制(一般不建议生产环境)。 +DATABASE_CONN_MAX_LIFETIME_MINUTES=30 +# DATABASE_CONN_MAX_IDLE_TIME_MINUTES:空闲连接最大存活时间。 +# 超过该时间的空闲连接会被回收,防止长时间闲置占用连接数。 +# 设置为 0 表示不限制(一般不建议生产环境)。 +DATABASE_CONN_MAX_IDLE_TIME_MINUTES=5 + # ----------------------------------------------------------------------------- # Redis Configuration # ----------------------------------------------------------------------------- # Leave empty for no password (default for local development) REDIS_PASSWORD= REDIS_DB=0 +# Redis 服务端最大客户端连接数(可选;主要用于 deploy/docker-compose-aicodex.yml) +REDIS_MAXCLIENTS=50000 +# Redis 连接池大小(默认 1024) +REDIS_POOL_SIZE=1024 +# Redis 最小空闲连接数(默认 10) +REDIS_MIN_IDLE_CONNS=10 REDIS_ENABLE_TLS=false # ----------------------------------------------------------------------------- @@ -119,6 +166,8 @@ RATE_LIMIT_OVERLOAD_COOLDOWN_MINUTES=10 # Gateway Scheduling (Optional) # 调度缓存与受控回源配置(缓存就绪且命中时不读 DB) # ----------------------------------------------------------------------------- +# 上游连接池:每主机最大连接数(默认 1024;流式/HTTP1.1 可调大) +GATEWAY_MAX_CONNS_PER_HOST=4096 # 粘性会话最大排队长度 GATEWAY_SCHEDULING_STICKY_SESSION_MAX_WAITING=3 # 粘性会话等待超时(时间段,例如 45s) diff --git a/deploy/config.example.yaml b/deploy/config.example.yaml index d9f5f2ab..ec520d62 100644 --- a/deploy/config.example.yaml +++ b/deploy/config.example.yaml @@ -161,7 +161,7 @@ gateway: max_idle_conns_per_host: 120 # Max connections per host # 每个主机的最大连接数 - max_conns_per_host: 240 + max_conns_per_host: 4096 # Idle connection timeout (seconds) # 空闲连接超时时间(秒) idle_conn_timeout_seconds: 90 @@ -384,6 +384,18 @@ database: # SSL mode: disable, require, verify-ca, verify-full # SSL 模式:disable(禁用), require(要求), verify-ca(验证CA), verify-full(完全验证) sslmode: "disable" + # Max open connections + # 最大打开连接数 + max_open_conns: 50 + # Max idle connections + # 最大空闲连接数 + max_idle_conns: 10 + # Connection max lifetime (minutes) + # 连接最大存活时间(分钟) + conn_max_lifetime_minutes: 30 + # Connection max idle time (minutes) + # 空闲连接最大存活时间(分钟) + conn_max_idle_time_minutes: 5 # ============================================================================= # Redis Configuration @@ -402,6 +414,12 @@ redis: # Database number (0-15) # 数据库编号(0-15) db: 0 + # Connection pool size (max concurrent connections) + # 连接池大小(最大并发连接数) + pool_size: 1024 + # Minimum number of idle connections + # 最小空闲连接数 + min_idle_conns: 10 # Enable TLS/SSL connection # 是否启用 TLS/SSL 连接 enable_tls: false diff --git a/deploy/docker-compose-aicodex.yml b/deploy/docker-compose-aicodex.yml new file mode 100644 index 00000000..8c045e30 --- /dev/null +++ b/deploy/docker-compose-aicodex.yml @@ -0,0 +1,226 @@ +# ============================================================================= +# Sub2API Docker Compose Host Configuration (Local Build) +# ============================================================================= +# Quick Start: +# 1. Copy .env.example to .env and configure +# 2. docker-compose -f docker-compose-host.yml up -d --build +# 3. Check logs: docker-compose -f docker-compose-host.yml logs -f sub2api +# 4. Access: http://localhost:8080 +# +# This configuration builds the image from source (Dockerfile in project root). +# All configuration is done via environment variables. +# No Setup Wizard needed - the system auto-initializes on first run. +# ============================================================================= + +services: + # =========================================================================== + # Sub2API Application + # =========================================================================== + sub2api: + #image: weishaw/sub2api:latest + image: yangjianbo/aicodex2api:latest + build: + context: .. + dockerfile: Dockerfile + container_name: sub2api + restart: unless-stopped + network_mode: host + ulimits: + nofile: + soft: 800000 + hard: 800000 + volumes: + # Data persistence (config.yaml will be auto-generated here) + - sub2api_data:/app/data + # Mount custom config.yaml (optional, overrides auto-generated config) + #- ./config.yaml:/app/data/config.yaml:ro + environment: + # ======================================================================= + # Auto Setup (REQUIRED for Docker deployment) + # ======================================================================= + - AUTO_SETUP=true + + # ======================================================================= + # Server Configuration + # ======================================================================= + - SERVER_HOST=0.0.0.0 + - SERVER_PORT=8080 + - SERVER_MODE=${SERVER_MODE:-release} + - RUN_MODE=${RUN_MODE:-standard} + + # ======================================================================= + # Database Configuration (PostgreSQL) + # ======================================================================= + # Using host network: point to host/external DB by DATABASE_HOST/DATABASE_PORT + - DATABASE_HOST=${DATABASE_HOST:-127.0.0.1} + - DATABASE_PORT=${DATABASE_PORT:-5432} + - DATABASE_USER=${POSTGRES_USER:-sub2api} + - DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} + - DATABASE_DBNAME=${POSTGRES_DB:-sub2api} + - DATABASE_SSLMODE=disable + - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} + - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} + - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} + - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} + + # ======================================================================= + # Gateway Configuration + # ======================================================================= + - GATEWAY_MAX_CONNS_PER_HOST=${GATEWAY_MAX_CONNS_PER_HOST:-1024} + + # ======================================================================= + # Redis Configuration + # ======================================================================= + # Using host network: point to host/external Redis by REDIS_HOST/REDIS_PORT + - REDIS_HOST=${REDIS_HOST:-127.0.0.1} + - REDIS_PORT=${REDIS_PORT:-6379} + - REDIS_PASSWORD=${REDIS_PASSWORD:-} + - REDIS_DB=${REDIS_DB:-0} + - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} + - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} + - REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false} + + # ======================================================================= + # Admin Account (auto-created on first run) + # ======================================================================= + - ADMIN_EMAIL=${ADMIN_EMAIL:-admin@sub2api.local} + - ADMIN_PASSWORD=${ADMIN_PASSWORD:-} + + # ======================================================================= + # JWT Configuration + # ======================================================================= + # Leave empty to auto-generate (recommended) + - JWT_SECRET=${JWT_SECRET:-} + - JWT_EXPIRE_HOUR=${JWT_EXPIRE_HOUR:-24} + + # ======================================================================= + # TOTP (2FA) Configuration + # ======================================================================= + # IMPORTANT: Set a fixed encryption key for TOTP secrets. If left empty, + # a random key will be generated on each startup, causing all existing + # TOTP configurations to become invalid (users won't be able to login + # with 2FA). + # Generate a secure key: openssl rand -hex 32 + - TOTP_ENCRYPTION_KEY=${TOTP_ENCRYPTION_KEY:-} + + # ======================================================================= + # Timezone Configuration + # This affects ALL time operations in the application: + # - Database timestamps + # - Usage statistics "today" boundary + # - Subscription expiry times + # - Log timestamps + # Common values: Asia/Shanghai, America/New_York, Europe/London, UTC + # ======================================================================= + - TZ=${TZ:-Asia/Shanghai} + + # ======================================================================= + # Gemini OAuth Configuration (for Gemini accounts) + # ======================================================================= + - GEMINI_OAUTH_CLIENT_ID=${GEMINI_OAUTH_CLIENT_ID:-} + - GEMINI_OAUTH_CLIENT_SECRET=${GEMINI_OAUTH_CLIENT_SECRET:-} + - GEMINI_OAUTH_SCOPES=${GEMINI_OAUTH_SCOPES:-} + - GEMINI_QUOTA_POLICY=${GEMINI_QUOTA_POLICY:-} + + # ======================================================================= + # Security Configuration (URL Allowlist) + # ======================================================================= + # Allow private IP addresses for CRS sync (for internal deployments) + - SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS=${SECURITY_URL_ALLOWLIST_ALLOW_PRIVATE_HOSTS:-true} + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8080/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + + # =========================================================================== + # PostgreSQL Database + # =========================================================================== + postgres: + image: postgres:18-alpine + container_name: sub2api-postgres + restart: unless-stopped + network_mode: host + ulimits: + nofile: + soft: 800000 + hard: 800000 + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${POSTGRES_USER:-sub2api} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} + - POSTGRES_DB=${POSTGRES_DB:-sub2api} + - TZ=${TZ:-Asia/Shanghai} + command: + - "postgres" + - "-c" + - "listen_addresses=127.0.0.1" + # 连接数上限:需要结合应用侧 DATABASE_MAX_OPEN_CONNS 调整。 + # 注意:max_connections 过大可能导致内存占用与上下文切换开销显著上升。 + - "-c" + - "max_connections=${POSTGRES_MAX_CONNECTIONS:-1024}" + # 典型内存参数(建议结合机器内存调优;不确定就保持默认或小步调大)。 + - "-c" + - "shared_buffers=${POSTGRES_SHARED_BUFFERS:-1GB}" + - "-c" + - "effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4GB}" + - "-c" + - "maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-128MB}" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-sub2api} -d ${POSTGRES_DB:-sub2api}"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 10s + # Note: bound to localhost only; not exposed to external network by default. + + # =========================================================================== + # Redis Cache + # =========================================================================== + redis: + image: redis:8-alpine + container_name: sub2api-redis + restart: unless-stopped + network_mode: host + ulimits: + nofile: + soft: 100000 + hard: 100000 + volumes: + - redis_data:/data + command: > + redis-server + --bind 127.0.0.1 + --maxclients ${REDIS_MAXCLIENTS:-50000} + --save 60 1 + --appendonly yes + --appendfsync everysec + ${REDIS_PASSWORD:+--requirepass ${REDIS_PASSWORD}} + environment: + - TZ=${TZ:-Asia/Shanghai} + # REDISCLI_AUTH is used by redis-cli for authentication (safer than -a flag) + - REDISCLI_AUTH=${REDIS_PASSWORD:-} + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 5s + +# ============================================================================= +# Volumes +# ============================================================================= +volumes: + sub2api_data: + driver: local + postgres_data: + driver: local + redis_data: + driver: local diff --git a/deploy/docker-compose-test.yml b/deploy/docker-compose-test.yml index bcda3141..81cd5222 100644 --- a/deploy/docker-compose-test.yml +++ b/deploy/docker-compose-test.yml @@ -57,6 +57,10 @@ services: - DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - DATABASE_DBNAME=${POSTGRES_DB:-sub2api} - DATABASE_SSLMODE=disable + - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} + - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} + - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} + - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} # ======================================================================= # Redis Configuration @@ -65,6 +69,8 @@ services: - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=${REDIS_DB:-0} + - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} + - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} # ======================================================================= # Admin Account (auto-created on first run) diff --git a/deploy/docker-compose.local.yml b/deploy/docker-compose.local.yml index 05ce129a..e778612c 100644 --- a/deploy/docker-compose.local.yml +++ b/deploy/docker-compose.local.yml @@ -62,6 +62,10 @@ services: - DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - DATABASE_DBNAME=${POSTGRES_DB:-sub2api} - DATABASE_SSLMODE=disable + - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} + - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} + - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} + - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} # ======================================================================= # Redis Configuration @@ -70,6 +74,8 @@ services: - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=${REDIS_DB:-0} + - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} + - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} - REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false} # ======================================================================= diff --git a/deploy/docker-compose.standalone.yml b/deploy/docker-compose.standalone.yml index 97903bc5..bb0041de 100644 --- a/deploy/docker-compose.standalone.yml +++ b/deploy/docker-compose.standalone.yml @@ -48,6 +48,10 @@ services: - DATABASE_PASSWORD=${DATABASE_PASSWORD:?DATABASE_PASSWORD is required} - DATABASE_DBNAME=${DATABASE_DBNAME:-sub2api} - DATABASE_SSLMODE=${DATABASE_SSLMODE:-disable} + - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} + - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} + - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} + - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} # ======================================================================= # Redis Configuration - Required @@ -56,6 +60,8 @@ services: - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=${REDIS_DB:-0} + - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} + - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} - REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false} # ======================================================================= diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 033731ac..4297ad0e 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -54,6 +54,10 @@ services: - DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required} - DATABASE_DBNAME=${POSTGRES_DB:-sub2api} - DATABASE_SSLMODE=disable + - DATABASE_MAX_OPEN_CONNS=${DATABASE_MAX_OPEN_CONNS:-50} + - DATABASE_MAX_IDLE_CONNS=${DATABASE_MAX_IDLE_CONNS:-10} + - DATABASE_CONN_MAX_LIFETIME_MINUTES=${DATABASE_CONN_MAX_LIFETIME_MINUTES:-30} + - DATABASE_CONN_MAX_IDLE_TIME_MINUTES=${DATABASE_CONN_MAX_IDLE_TIME_MINUTES:-5} # ======================================================================= # Redis Configuration @@ -62,6 +66,8 @@ services: - REDIS_PORT=6379 - REDIS_PASSWORD=${REDIS_PASSWORD:-} - REDIS_DB=${REDIS_DB:-0} + - REDIS_POOL_SIZE=${REDIS_POOL_SIZE:-1024} + - REDIS_MIN_IDLE_CONNS=${REDIS_MIN_IDLE_CONNS:-10} - REDIS_ENABLE_TLS=${REDIS_ENABLE_TLS:-false} # =======================================================================