diff --git a/.env.example b/.env.example index 931d4109b..a529dd673 100644 --- a/.env.example +++ b/.env.example @@ -66,7 +66,7 @@ ADMIN_USERNAME=admin123456 # docker compose 下 app 启动前自动执行 pending migration/backfill(默认 true) # AETHER_GATEWAY_AUTO_PREPARE_DATABASE=true -# PostgreSQL 连接池配置(默认按 CPU 自动计算;正式高并发环境可显式预算) +# PostgreSQL 连接池配置(默认每核 4 条、总池至少 32 条且最多 100 条;多实例部署应显式分配每实例预算) # AETHER_GATEWAY_DATA_POSTGRES_MIN_CONNECTIONS=12 # AETHER_GATEWAY_DATA_POSTGRES_MAX_CONNECTIONS=80 # AETHER_GATEWAY_MAX_IN_FLIGHT_REQUESTS=2048 diff --git a/README.md b/README.md index e3ef2857b..de2e3f10d 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ Aether Tunnel 是配套的正向代理节点,部署在海外 VPS 上,为墙 - `APP_PORT`:`aether-gateway` 唯一监听端口,固定绑定 `0.0.0.0:${APP_PORT}` - `DATABASE_URL`:数据库连接串;SQLite 例如 `sqlite:///opt/aether/data/aether.db`,Postgres 例如 `postgresql://postgres:aether@postgres:5432/aether` -- `AETHER_GATEWAY_DATA_POSTGRES_MIN_CONNECTIONS` / `AETHER_GATEWAY_DATA_POSTGRES_MAX_CONNECTIONS`:数据库连接池手动覆盖值;未配置时会自动推导,SQLite 固定 `1/1`,Postgres/MySQL 按 CPU 核心数计算并默认封顶 `100` +- `AETHER_GATEWAY_DATA_POSTGRES_MIN_CONNECTIONS` / `AETHER_GATEWAY_DATA_POSTGRES_MAX_CONNECTIONS`:数据库连接池手动覆盖值;未配置时 SQLite 固定 `1/1`,Postgres/MySQL 按每核 `4` 条自动推导,总池范围为 `32-100`。该预算按进程计算,多实例部署应按数据库连接上限显式分配 - `AETHER_GATEWAY_MAX_IN_FLIGHT_REQUESTS`:单实例请求并发上限;未配置时按 CPU 自动推导(基础范围 `512-65536`),低文件描述符预算时会进一步下调 - `AETHER_GATEWAY_REQUEST_BODY_BUFFER_BUDGET_MB`:单实例同时读取和解压请求体的加权内存预算,默认 `256MB` - `AETHER_GATEWAY_REQUEST_BODY_READ_TIMEOUT_MS`:请求体完整读取超时,默认 `120000ms` diff --git a/apps/aether-gateway/src/data/config.rs b/apps/aether-gateway/src/data/config.rs index 7e5b1d8f7..c694b8c26 100644 --- a/apps/aether-gateway/src/data/config.rs +++ b/apps/aether-gateway/src/data/config.rs @@ -195,6 +195,35 @@ mod tests { assert_eq!(background.pool.min_connections, 1); } + #[test] + fn runtime_pool_split_gives_default_small_server_more_foreground_capacity() { + let config = GatewayDataConfig::from_database_config( + SqlDatabaseConfig::new( + DatabaseDriver::Postgres, + "postgres://localhost/aether", + SqlPoolConfig { + min_connections: 4, + max_connections: 32, + ..SqlPoolConfig::default() + }, + ) + .expect("database config should be valid"), + ); + + let (foreground, background) = config.split_runtime_pools_with_background_max(None); + let foreground = foreground.database().expect("foreground database"); + let background = background + .expect("background database config") + .database() + .expect("background database") + .clone(); + + assert_eq!(foreground.pool.max_connections, 26); + assert_eq!(background.pool.max_connections, 6); + assert_eq!(foreground.pool.min_connections, 4); + assert_eq!(background.pool.min_connections, 1); + } + #[test] fn runtime_pool_split_can_be_disabled_or_degrade_for_single_connection() { let mut database = SqlDatabaseConfig::sqlite_default(); diff --git a/apps/aether-gateway/src/main.rs b/apps/aether-gateway/src/main.rs index 13e95d533..6bf02877a 100644 --- a/apps/aether-gateway/src/main.rs +++ b/apps/aether-gateway/src/main.rs @@ -261,7 +261,7 @@ const DEFAULT_SQLITE_POOL_MAX_CONNECTIONS: u32 = 1; const AUTO_SERVER_SQL_POOL_CONNECTIONS_PER_CPU: u32 = 4; const AUTO_SERVER_SQL_POOL_MIN_CONNECTIONS_FLOOR: u32 = 4; const AUTO_SERVER_SQL_POOL_MIN_CONNECTIONS_CAP: u32 = 16; -const AUTO_SERVER_SQL_POOL_MAX_CONNECTIONS_FLOOR: u32 = 20; +const AUTO_SERVER_SQL_POOL_MAX_CONNECTIONS_FLOOR: u32 = 32; const AUTO_SERVER_SQL_POOL_MAX_CONNECTIONS_CAP: u32 = 100; const DEFAULT_USAGE_QUEUE_WORKERS_CAP: usize = 8; const AUTO_USAGE_QUEUE_WORKERS_MIN: usize = 2; @@ -2837,7 +2837,11 @@ mod tests { fn gateway_data_pool_cpu_sizing_examples() { let two_cpu = automatic_sql_pool_config_for_parallelism(DatabaseDriver::Postgres, 2); assert_eq!(two_cpu.min_connections, 4); - assert_eq!(two_cpu.max_connections, 20); + assert_eq!(two_cpu.max_connections, 32); + + let four_cpu = automatic_sql_pool_config_for_parallelism(DatabaseDriver::Postgres, 4); + assert_eq!(four_cpu.min_connections, 4); + assert_eq!(four_cpu.max_connections, 32); let eight_cpu = automatic_sql_pool_config_for_parallelism(DatabaseDriver::Postgres, 8); assert_eq!(eight_cpu.min_connections, 8);