nghttpx: Add --max-worker-processes option

This commit is contained in:
Tatsuhiro Tsujikawa 2021-09-29 22:12:10 +09:00
parent d9c7631dcb
commit 0266c458a3
4 changed files with 43 additions and 1 deletions

View File

@ -195,6 +195,7 @@ OPTIONS = [
"frontend-quic-server-id", "frontend-quic-server-id",
"frontend-quic-secret-file", "frontend-quic-secret-file",
"rlimit-memlock", "rlimit-memlock",
"max-worker-processes",
] ]
LOGVARS = [ LOGVARS = [

View File

@ -300,6 +300,17 @@ void worker_process_remove(const WorkerProcess *wp) {
} }
} // namespace } // namespace
namespace {
void worker_process_adjust_limit() {
auto config = get_config();
if (config->max_worker_processes &&
worker_processes.size() > config->max_worker_processes) {
worker_processes.pop_front();
}
}
} // namespace
namespace { namespace {
void worker_process_remove_all() { void worker_process_remove_all() {
std::deque<std::unique_ptr<WorkerProcess>>().swap(worker_processes); std::deque<std::unique_ptr<WorkerProcess>>().swap(worker_processes);
@ -3201,6 +3212,19 @@ Process:
process. nghttpx still spawns additional process if process. nghttpx still spawns additional process if
neverbleed is used. In the single process mode, the neverbleed is used. In the single process mode, the
signal handling feature is disabled. signal handling feature is disabled.
--max-worker-processes=<N>
The maximum number of worker processes. nghttpx spawns
new worker process when it reloads its configuration.
The previous worker process enters graceful termination
period and will terminate when it finishes handling the
existing connections. However, if reloading
configurations happen very frequently, the worker
processes might be piled up if they take a bit long time
to finish the existing connections. With this option,
if the number of worker processes exceeds the given
value, the oldest worker process is terminated
immediately. Specifying 0 means no limit and it is the
default behaviour.
Scripting: Scripting:
--mruby-file=<PATH> --mruby-file=<PATH>
@ -3773,6 +3797,8 @@ void reload_config(WorkerProcess *wp) {
ipc_send(last_wp.get(), SHRPX_IPC_UNLOAD_BPF_OBJECT); ipc_send(last_wp.get(), SHRPX_IPC_UNLOAD_BPF_OBJECT);
#endif // ENABLE_HTTP3 #endif // ENABLE_HTTP3
worker_process_adjust_limit();
if (!get_config()->pid_file.empty()) { if (!get_config()->pid_file.empty()) {
save_pid(); save_pid();
} }
@ -4101,6 +4127,7 @@ int main(int argc, char **argv) {
{SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE.c_str(), required_argument, &flag, {SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE.c_str(), required_argument, &flag,
186}, 186},
{SHRPX_OPT_RLIMIT_MEMLOCK.c_str(), required_argument, &flag, 187}, {SHRPX_OPT_RLIMIT_MEMLOCK.c_str(), required_argument, &flag, 187},
{SHRPX_OPT_MAX_WORKER_PROCESSES.c_str(), required_argument, &flag, 188},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -4992,6 +5019,10 @@ int main(int argc, char **argv) {
// --rlimit-memlock // --rlimit-memlock
cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_MEMLOCK, StringRef{optarg}); cmdcfgs.emplace_back(SHRPX_OPT_RLIMIT_MEMLOCK, StringRef{optarg});
break; break;
case 188:
// --max-worker-processes
cmdcfgs.emplace_back(SHRPX_OPT_MAX_WORKER_PROCESSES, StringRef{optarg});
break;
default: default:
break; break;
} }

View File

@ -2248,6 +2248,9 @@ int option_lookup_token(const char *name, size_t namelen) {
} }
break; break;
case 's': case 's':
if (util::strieq_l("max-worker-processe", name, 19)) {
return SHRPX_OPTID_MAX_WORKER_PROCESSES;
}
if (util::strieq_l("tls13-client-cipher", name, 19)) { if (util::strieq_l("tls13-client-cipher", name, 19)) {
return SHRPX_OPTID_TLS13_CLIENT_CIPHERS; return SHRPX_OPTID_TLS13_CLIENT_CIPHERS;
} }
@ -4139,6 +4142,8 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return 0; return 0;
} }
case SHRPX_OPTID_MAX_WORKER_PROCESSES:
return parse_uint(&config->max_worker_processes, opt, optarg);
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";

View File

@ -396,6 +396,8 @@ constexpr auto SHRPX_OPT_FRONTEND_QUIC_SERVER_ID =
constexpr auto SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE = constexpr auto SHRPX_OPT_FRONTEND_QUIC_SECRET_FILE =
StringRef::from_lit("frontend-quic-secret-file"); StringRef::from_lit("frontend-quic-secret-file");
constexpr auto SHRPX_OPT_RLIMIT_MEMLOCK = StringRef::from_lit("rlimit-memlock"); constexpr auto SHRPX_OPT_RLIMIT_MEMLOCK = StringRef::from_lit("rlimit-memlock");
constexpr auto SHRPX_OPT_MAX_WORKER_PROCESSES =
StringRef::from_lit("max-worker-processes");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -1075,7 +1077,8 @@ struct Config {
single_process{false}, single_process{false},
single_thread{false}, single_thread{false},
ignore_per_pattern_mruby_error{false}, ignore_per_pattern_mruby_error{false},
ev_loop_flags{0} { ev_loop_flags{0},
max_worker_processes{0} {
} }
~Config(); ~Config();
@ -1129,6 +1132,7 @@ struct Config {
bool ignore_per_pattern_mruby_error; bool ignore_per_pattern_mruby_error;
// flags passed to ev_default_loop() and ev_loop_new() // flags passed to ev_default_loop() and ev_loop_new()
int ev_loop_flags; int ev_loop_flags;
size_t max_worker_processes;
}; };
const Config *get_config(); const Config *get_config();
@ -1255,6 +1259,7 @@ enum {
SHRPX_OPTID_MAX_HEADER_FIELDS, SHRPX_OPTID_MAX_HEADER_FIELDS,
SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS, SHRPX_OPTID_MAX_REQUEST_HEADER_FIELDS,
SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS, SHRPX_OPTID_MAX_RESPONSE_HEADER_FIELDS,
SHRPX_OPTID_MAX_WORKER_PROCESSES,
SHRPX_OPTID_MRUBY_FILE, SHRPX_OPTID_MRUBY_FILE,
SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO, SHRPX_OPTID_NO_ADD_X_FORWARDED_PROTO,
SHRPX_OPTID_NO_HOST_REWRITE, SHRPX_OPTID_NO_HOST_REWRITE,