Add configurable CPU count option for containerized environments (#1717)
This PR adds a new `--cpus` configuration option to address CPU detection issues in virtualized and containerized environments where `_SC_NPROCESSORS_CONF` and `_SC_NPROCESSORS_ONLN` return host CPU counts instead of allocated container CPUs. ## Problem In containerized deployments, coturn detects the host's CPU count (e.g., 128 CPUs) instead of the container's allocated CPUs (e.g., 2 CPUs). This causes the server to create excessive relay threads and database connections, leading to resource exhaustion and performance issues. ## Solution Added a new `cpus` configuration option that allows manual override of CPU detection: ### Command Line Usage ```bash turnserver --cpus 2 ``` ### Configuration File Usage ```ini # Override system CPU count detection for containers cpus=2 ``` ## Key Features - **Backward Compatible**: No changes needed for existing deployments - **Input Validation**: Values must be between 1 and 128 with proper error handling - **Comprehensive Documentation**: Updated man pages and example config files - **Both Interfaces**: Works via command line and configuration file ## Testing The implementation has been thoroughly tested: ```bash # Container with 2 allocated CPUs on 128-CPU host $ turnserver --cpus 2 INFO: System cpu num is 128 # Host detection INFO: System enable num is 128 # Host detection INFO: Configured cpu num is 2 # Override applied INFO: Total General servers: 2 # Correct thread count ``` - ✅ Command line option: `--cpus 8` creates 8 relay servers - ✅ Config file option: `cpus=6` creates 6 relay servers - ✅ Error handling: Invalid values show appropriate errors - ✅ Default behavior: Without option, uses system detection - ✅ RFC5769 tests: All protocol tests still pass ## Files Modified - `src/apps/relay/mainrelay.c` - Core implementation - `src/apps/relay/mainrelay.h` - Added configuration flag - `examples/etc/turnserver.conf` - Added documentation and example - `man/man1/turnserver.1` - Updated man page This change directly addresses the resource consumption issues in containerized environments while maintaining full backward compatibility. Fixes #1628.
This commit is contained in:
parent
5ab95e1a5a
commit
99984fbccd
@ -164,6 +164,14 @@
|
||||
#
|
||||
#relay-threads=0
|
||||
|
||||
# Override system CPU count detection. Use this number instead of the
|
||||
# auto-detected CPU count. Useful in virtualized/containerized environments
|
||||
# where the system reports the host CPU count instead of the allocated
|
||||
# container CPUs. This affects the default number of relay threads when
|
||||
# relay-threads is not explicitly specified.
|
||||
#
|
||||
#cpus=2
|
||||
|
||||
# Lower and upper bounds of the UDP relay endpoints:
|
||||
# (default values are 49152 and 65535)
|
||||
#
|
||||
|
||||
@ -591,6 +591,14 @@ will be employed (OS\-dependent). In the older Linux systems
|
||||
per network listening endpoint \- unless "\fB\-m\fP 0" or "\fB\-m\fP 1" is set.
|
||||
.TP
|
||||
.B
|
||||
\fB\-\-cpus\fP
|
||||
Override system CPU count detection. Use this number instead of the
|
||||
auto\-detected CPU count. Useful in virtualized/containerized environments
|
||||
where the system reports the host CPU count instead of the allocated
|
||||
container CPUs. This affects the default number of relay threads when
|
||||
\fB\-\-relay\-threads\fP is not explicitly specified.
|
||||
.TP
|
||||
.B
|
||||
\fB\-\-min\-port\fP
|
||||
Lower bound of the UDP port range for relay
|
||||
endpoints allocation.
|
||||
|
||||
@ -225,6 +225,7 @@ turn_params_t turn_params = {
|
||||
|
||||
///////////// CPUs //////////////////
|
||||
DEFAULT_CPUS_NUMBER,
|
||||
false, /* cpus_configured */
|
||||
|
||||
///////// Encryption /////////
|
||||
"", /* secret_key_file */
|
||||
@ -1024,6 +1025,11 @@ static char Usage[] =
|
||||
" In older systems (pre-Linux 3.9) the number of UDP relay threads "
|
||||
"always equals\n"
|
||||
" the number of listening endpoints (unless -m 0 is set).\n"
|
||||
" --cpus <number> Override system CPU count detection. Use this number\n"
|
||||
" instead of the auto-detected CPU count.\n"
|
||||
" Useful in virtualized/containerized environments where\n"
|
||||
" the system reports the host CPU count instead of\n"
|
||||
" the allocated container CPUs.\n"
|
||||
" --min-port <port> Lower bound of the UDP port range for relay endpoints "
|
||||
"allocation.\n"
|
||||
" Default value is 49152, according to RFC 5766.\n"
|
||||
@ -1506,7 +1512,8 @@ enum EXTRA_OPTS {
|
||||
STUN_BACKWARD_COMPATIBILITY_OPT,
|
||||
RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT,
|
||||
RESPOND_HTTP_UNSUPPORTED_OPT,
|
||||
VERSION_OPT
|
||||
VERSION_OPT,
|
||||
CPUS_OPT
|
||||
};
|
||||
|
||||
struct myoption {
|
||||
@ -1652,6 +1659,7 @@ static const struct myoption long_options[] = {
|
||||
{"respond-http-unsupported", optional_argument, NULL, RESPOND_HTTP_UNSUPPORTED_OPT},
|
||||
{"version", optional_argument, NULL, VERSION_OPT},
|
||||
{"syslog-facility", required_argument, NULL, SYSLOG_FACILITY_OPT},
|
||||
{"cpus", required_argument, NULL, CPUS_OPT},
|
||||
{NULL, no_argument, NULL, 0}};
|
||||
|
||||
static const struct myoption admin_long_options[] = {
|
||||
@ -2367,6 +2375,20 @@ static void set_option(int c, char *value) {
|
||||
case RESPOND_HTTP_UNSUPPORTED_OPT:
|
||||
turn_params.respond_http_unsupported = get_bool_value(value);
|
||||
break;
|
||||
case CPUS_OPT: {
|
||||
int cpus = atoi(value);
|
||||
if (cpus < 1) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ERROR: cpus value must be positive\n");
|
||||
} else if (cpus > MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) {
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WARNING: max number of cpus is %d.\n",
|
||||
MAX_NUMBER_OF_GENERAL_RELAY_SERVERS);
|
||||
turn_params.cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS;
|
||||
turn_params.cpus_configured = true;
|
||||
} else {
|
||||
turn_params.cpus = (unsigned long)cpus;
|
||||
turn_params.cpus_configured = true;
|
||||
}
|
||||
} break;
|
||||
|
||||
/* these options have been already taken care of before: */
|
||||
case 'l':
|
||||
@ -3034,23 +3056,6 @@ int main(int argc, char **argv) {
|
||||
// Zero pass apply the log options.
|
||||
read_config_file(argc, argv, 0);
|
||||
|
||||
{
|
||||
unsigned long cpus = get_system_active_number_of_cpus();
|
||||
if (cpus > 0) {
|
||||
turn_params.cpus = cpus;
|
||||
}
|
||||
if (turn_params.cpus < DEFAULT_CPUS_NUMBER) {
|
||||
turn_params.cpus = DEFAULT_CPUS_NUMBER;
|
||||
} else if (turn_params.cpus > MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) {
|
||||
turn_params.cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS;
|
||||
}
|
||||
|
||||
turn_params.general_relay_servers_number = (turnserver_id)turn_params.cpus;
|
||||
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "System cpu num is %lu\n", get_system_number_of_cpus());
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "System enable num is %lu\n", get_system_active_number_of_cpus());
|
||||
}
|
||||
|
||||
// First pass read other config options
|
||||
read_config_file(argc, argv, 1);
|
||||
|
||||
@ -3063,6 +3068,25 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
}
|
||||
|
||||
// CPU detection and configuration
|
||||
if (!turn_params.cpus_configured) {
|
||||
unsigned long cpus = get_system_active_number_of_cpus();
|
||||
if (cpus > 0) {
|
||||
turn_params.cpus = cpus;
|
||||
}
|
||||
}
|
||||
if (turn_params.cpus < DEFAULT_CPUS_NUMBER) {
|
||||
turn_params.cpus = DEFAULT_CPUS_NUMBER;
|
||||
} else if (turn_params.cpus > MAX_NUMBER_OF_GENERAL_RELAY_SERVERS) {
|
||||
turn_params.cpus = MAX_NUMBER_OF_GENERAL_RELAY_SERVERS;
|
||||
}
|
||||
|
||||
turn_params.general_relay_servers_number = (turnserver_id)turn_params.cpus;
|
||||
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "System cpu num is %lu\n", get_system_number_of_cpus());
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "System enable num is %lu\n", get_system_active_number_of_cpus());
|
||||
TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Configured cpu num is %lu\n", turn_params.cpus);
|
||||
|
||||
// Second pass read -u options
|
||||
read_config_file(argc, argv, 2);
|
||||
|
||||
|
||||
@ -334,6 +334,7 @@ typedef struct _turn_params_ {
|
||||
/////// CPUs //////////////
|
||||
|
||||
unsigned long cpus;
|
||||
bool cpus_configured;
|
||||
|
||||
///////// Encryption /////////
|
||||
char secret_key_file[1025];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user