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
|
#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:
|
# Lower and upper bounds of the UDP relay endpoints:
|
||||||
# (default values are 49152 and 65535)
|
# (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.
|
per network listening endpoint \- unless "\fB\-m\fP 0" or "\fB\-m\fP 1" is set.
|
||||||
.TP
|
.TP
|
||||||
.B
|
.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
|
\fB\-\-min\-port\fP
|
||||||
Lower bound of the UDP port range for relay
|
Lower bound of the UDP port range for relay
|
||||||
endpoints allocation.
|
endpoints allocation.
|
||||||
|
|||||||
@ -225,6 +225,7 @@ turn_params_t turn_params = {
|
|||||||
|
|
||||||
///////////// CPUs //////////////////
|
///////////// CPUs //////////////////
|
||||||
DEFAULT_CPUS_NUMBER,
|
DEFAULT_CPUS_NUMBER,
|
||||||
|
false, /* cpus_configured */
|
||||||
|
|
||||||
///////// Encryption /////////
|
///////// Encryption /////////
|
||||||
"", /* secret_key_file */
|
"", /* secret_key_file */
|
||||||
@ -1024,6 +1025,11 @@ static char Usage[] =
|
|||||||
" In older systems (pre-Linux 3.9) the number of UDP relay threads "
|
" In older systems (pre-Linux 3.9) the number of UDP relay threads "
|
||||||
"always equals\n"
|
"always equals\n"
|
||||||
" the number of listening endpoints (unless -m 0 is set).\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 "
|
" --min-port <port> Lower bound of the UDP port range for relay endpoints "
|
||||||
"allocation.\n"
|
"allocation.\n"
|
||||||
" Default value is 49152, according to RFC 5766.\n"
|
" Default value is 49152, according to RFC 5766.\n"
|
||||||
@ -1506,7 +1512,8 @@ enum EXTRA_OPTS {
|
|||||||
STUN_BACKWARD_COMPATIBILITY_OPT,
|
STUN_BACKWARD_COMPATIBILITY_OPT,
|
||||||
RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT,
|
RESPONSE_ORIGIN_ONLY_WITH_RFC5780_OPT,
|
||||||
RESPOND_HTTP_UNSUPPORTED_OPT,
|
RESPOND_HTTP_UNSUPPORTED_OPT,
|
||||||
VERSION_OPT
|
VERSION_OPT,
|
||||||
|
CPUS_OPT
|
||||||
};
|
};
|
||||||
|
|
||||||
struct myoption {
|
struct myoption {
|
||||||
@ -1652,6 +1659,7 @@ static const struct myoption long_options[] = {
|
|||||||
{"respond-http-unsupported", optional_argument, NULL, RESPOND_HTTP_UNSUPPORTED_OPT},
|
{"respond-http-unsupported", optional_argument, NULL, RESPOND_HTTP_UNSUPPORTED_OPT},
|
||||||
{"version", optional_argument, NULL, VERSION_OPT},
|
{"version", optional_argument, NULL, VERSION_OPT},
|
||||||
{"syslog-facility", required_argument, NULL, SYSLOG_FACILITY_OPT},
|
{"syslog-facility", required_argument, NULL, SYSLOG_FACILITY_OPT},
|
||||||
|
{"cpus", required_argument, NULL, CPUS_OPT},
|
||||||
{NULL, no_argument, NULL, 0}};
|
{NULL, no_argument, NULL, 0}};
|
||||||
|
|
||||||
static const struct myoption admin_long_options[] = {
|
static const struct myoption admin_long_options[] = {
|
||||||
@ -2367,6 +2375,20 @@ static void set_option(int c, char *value) {
|
|||||||
case RESPOND_HTTP_UNSUPPORTED_OPT:
|
case RESPOND_HTTP_UNSUPPORTED_OPT:
|
||||||
turn_params.respond_http_unsupported = get_bool_value(value);
|
turn_params.respond_http_unsupported = get_bool_value(value);
|
||||||
break;
|
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: */
|
/* these options have been already taken care of before: */
|
||||||
case 'l':
|
case 'l':
|
||||||
@ -3034,23 +3056,6 @@ int main(int argc, char **argv) {
|
|||||||
// Zero pass apply the log options.
|
// Zero pass apply the log options.
|
||||||
read_config_file(argc, argv, 0);
|
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
|
// First pass read other config options
|
||||||
read_config_file(argc, argv, 1);
|
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
|
// Second pass read -u options
|
||||||
read_config_file(argc, argv, 2);
|
read_config_file(argc, argv, 2);
|
||||||
|
|
||||||
|
|||||||
@ -334,6 +334,7 @@ typedef struct _turn_params_ {
|
|||||||
/////// CPUs //////////////
|
/////// CPUs //////////////
|
||||||
|
|
||||||
unsigned long cpus;
|
unsigned long cpus;
|
||||||
|
bool cpus_configured;
|
||||||
|
|
||||||
///////// Encryption /////////
|
///////// Encryption /////////
|
||||||
char secret_key_file[1025];
|
char secret_key_file[1025];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user