diff --git a/Cargo.toml b/Cargo.toml index 5d4992ffd1..8a5ec78aa4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,7 @@ itertools = "0.14" keyed_priority_queue = "0.4" libc = "0.2" log = "0.4" -nix = { version = "0.29", features = ["socket", "sched", "uio", "fs", "ioctl", "user", "net", "mount"] } +nix = { version = "0.29", features = ["socket", "sched", "uio", "fs", "ioctl", "user", "net", "mount", "resource" ] } once_cell = "1.21" num_cpus = "1.16" ppp = "2.3" diff --git a/src/main.rs b/src/main.rs index f11bafeec6..9b2ce84ee5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,8 +14,9 @@ extern crate core; +use nix::sys::resource::{Resource, getrlimit, setrlimit}; use std::sync::Arc; -use tracing::info; +use tracing::{info, warn}; use ztunnel::*; #[cfg(feature = "jemalloc")] @@ -28,6 +29,26 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[unsafe(export_name = "malloc_conf")] pub static malloc_conf: &[u8] = b"prof:true,prof_active:true,lg_prof_sample:19\0"; +// We use this on Unix systems to increase the number of open file descriptors +// if possible. This is useful for high-load scenarios where the default limit +// is too low, which can lead to droopped connections and other issues: +// see: https://github.com/istio/ztunnel/issues/1585 +fn increase_open_files_limit() { + #[cfg(unix)] + if let Ok((soft_limit, hard_limit)) = getrlimit(Resource::RLIMIT_NOFILE) { + if let Err(e) = setrlimit(Resource::RLIMIT_NOFILE, hard_limit, hard_limit) { + warn!("failed to set file descriptor limits: {e}"); + } else { + info!( + "set file descriptor limits from {} to {}", + soft_limit, hard_limit + ); + } + } else { + warn!("failed to get file descriptor limits"); + } +} + fn main() -> anyhow::Result<()> { let _log_flush = telemetry::setup_logging(); @@ -74,6 +95,7 @@ fn version() -> anyhow::Result<()> { async fn proxy(cfg: Arc) -> anyhow::Result<()> { info!("version: {}", version::BuildInfo::new()); + increase_open_files_limit(); info!("running with config: {}", serde_yaml::to_string(&cfg)?); app::build(cfg).await?.wait_termination().await }