nghttpx: Add option to specify HPACK encoder/decoder dynamic table size

This commit is contained in:
Tatsuhiro Tsujikawa 2016-09-12 22:53:02 +09:00
parent 743fc4a3c3
commit f4016644a9
6 changed files with 164 additions and 4 deletions

View File

@ -142,6 +142,10 @@ OPTIONS = [
"frontend-http2-connection-window-size", "frontend-http2-connection-window-size",
"backend-http2-window-size", "backend-http2-window-size",
"backend-http2-connection-window-size", "backend-http2-connection-window-size",
"frontend-http2-encoder-dynamic-table-size",
"frontend-http2-decoder-dynamic-table-size",
"backend-http2-encoder-dynamic-table-size",
"backend-http2-decoder-dynamic-table-size",
] ]
LOGVARS = [ LOGVARS = [

View File

@ -1345,14 +1345,21 @@ void fill_default_config(Config *config) {
upstreamconf.connection_window_size = 64_k - 1; upstreamconf.connection_window_size = 64_k - 1;
upstreamconf.max_concurrent_streams = 100; upstreamconf.max_concurrent_streams = 100;
upstreamconf.encoder_dynamic_table_size = 4_k;
upstreamconf.decoder_dynamic_table_size = 4_k;
nghttp2_option_new(&upstreamconf.option); nghttp2_option_new(&upstreamconf.option);
nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1); nghttp2_option_set_no_auto_window_update(upstreamconf.option, 1);
nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1); nghttp2_option_set_no_recv_client_magic(upstreamconf.option, 1);
nghttp2_option_set_max_deflate_dynamic_table_size(
upstreamconf.option, upstreamconf.encoder_dynamic_table_size);
// For API endpoint, we enable automatic window update. This is // For API endpoint, we enable automatic window update. This is
// because we are a sink. // because we are a sink.
nghttp2_option_new(&upstreamconf.alt_mode_option); nghttp2_option_new(&upstreamconf.alt_mode_option);
nghttp2_option_set_no_recv_client_magic(upstreamconf.alt_mode_option, 1); nghttp2_option_set_no_recv_client_magic(upstreamconf.alt_mode_option, 1);
nghttp2_option_set_max_deflate_dynamic_table_size(
upstreamconf.alt_mode_option, upstreamconf.encoder_dynamic_table_size);
} }
{ {
@ -1367,9 +1374,14 @@ void fill_default_config(Config *config) {
downstreamconf.connection_window_size = (1u << 31) - 1; downstreamconf.connection_window_size = (1u << 31) - 1;
downstreamconf.max_concurrent_streams = 100; downstreamconf.max_concurrent_streams = 100;
downstreamconf.encoder_dynamic_table_size = 4_k;
downstreamconf.decoder_dynamic_table_size = 4_k;
nghttp2_option_new(&downstreamconf.option); nghttp2_option_new(&downstreamconf.option);
nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1); nghttp2_option_set_no_auto_window_update(downstreamconf.option, 1);
nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100); nghttp2_option_set_peer_max_concurrent_streams(downstreamconf.option, 100);
nghttp2_option_set_max_deflate_dynamic_table_size(
downstreamconf.option, downstreamconf.encoder_dynamic_table_size);
} }
auto &loggingconf = config->logging; auto &loggingconf = config->logging;
@ -2053,6 +2065,36 @@ HTTP/2 and SPDY:
be adjusted using --frontend-http2-window-size option as be adjusted using --frontend-http2-window-size option as
well. This option is only effective on recent Linux well. This option is only effective on recent Linux
platform. platform.
--frontend-http2-encoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the frontend HTTP/2 connection. The decoder (client)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value client specified.
Default: )"
<< util::utos_unit(
get_config()->http2.upstream.encoder_dynamic_table_size) << R"(
--frontend-http2-decoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the frontend HTTP/2 connection.
Default: )"
<< util::utos_unit(
get_config()->http2.upstream.decoder_dynamic_table_size) << R"(
--backend-http2-encoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK encoder
in the backend HTTP/2 connection. The decoder (backend)
specifies the maximum dynamic table size it accepts.
Then the negotiated dynamic table size is the minimum of
this option value and the value backend specified.
Default: )"
<< util::utos_unit(
get_config()->http2.downstream.encoder_dynamic_table_size) << R"(
--backend-http2-decoder-dynamic-table-size=<SIZE>
Specify the maximum dynamic table size of HPACK decoder
in the backend HTTP/2 connection.
Default: )"
<< util::utos_unit(
get_config()->http2.downstream.decoder_dynamic_table_size) << R"(
Mode: Mode:
(default mode) (default mode)
@ -2875,6 +2917,14 @@ int main(int argc, char **argv) {
134}, 134},
{SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(), {SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
required_argument, &flag, 135}, required_argument, &flag, 135},
{SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
required_argument, &flag, 136},
{SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
required_argument, &flag, 137},
{SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE.c_str(),
required_argument, &flag, 138},
{SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE.c_str(),
required_argument, &flag, 139},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -3512,6 +3562,28 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE, cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE,
StringRef{optarg}); StringRef{optarg});
break; break;
case 136:
// --frontend-http2-encoder-dynamic-table-size
cmdcfgs.emplace_back(
SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
StringRef{optarg});
break;
case 137:
// --frontend-http2-decoder-dynamic-table-size
cmdcfgs.emplace_back(
SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
StringRef{optarg});
break;
case 138:
// --backend-http2-encoder-dynamic-table-size
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
StringRef{optarg});
break;
case 139:
// --backend-http2-decoder-dynamic-table-size
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
StringRef{optarg});
break;
default: default:
break; break;
} }

View File

@ -1733,9 +1733,29 @@ int option_lookup_token(const char *name, size_t namelen) {
break; break;
} }
break; break;
case 40:
switch (name[39]) {
case 'e':
if (util::strieq_l("backend-http2-decoder-dynamic-table-siz", name, 39)) {
return SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE;
}
if (util::strieq_l("backend-http2-encoder-dynamic-table-siz", name, 39)) {
return SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE;
}
break;
}
break;
case 41: case 41:
switch (name[40]) { switch (name[40]) {
case 'e': case 'e':
if (util::strieq_l("frontend-http2-decoder-dynamic-table-siz", name,
40)) {
return SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE;
}
if (util::strieq_l("frontend-http2-encoder-dynamic-table-siz", name,
40)) {
return SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE;
}
if (util::strieq_l("frontend-http2-optimize-write-buffer-siz", name, if (util::strieq_l("frontend-http2-optimize-write-buffer-siz", name,
40)) { 40)) {
return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE; return SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE;
@ -2773,6 +2793,38 @@ int parse_config(Config *config, int optid, const StringRef &opt,
} }
return 0; return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE:
if (parse_uint_with_unit(&config->http2.upstream.encoder_dynamic_table_size,
opt, optarg) != 0) {
return -1;
}
nghttp2_option_set_max_deflate_dynamic_table_size(
config->http2.upstream.option,
config->http2.upstream.encoder_dynamic_table_size);
nghttp2_option_set_max_deflate_dynamic_table_size(
config->http2.upstream.alt_mode_option,
config->http2.upstream.encoder_dynamic_table_size);
return 0;
case SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE:
return parse_uint_with_unit(
&config->http2.upstream.decoder_dynamic_table_size, opt, optarg);
case SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE:
if (parse_uint_with_unit(
&config->http2.downstream.encoder_dynamic_table_size, opt,
optarg) != 0) {
return -1;
}
nghttp2_option_set_max_deflate_dynamic_table_size(
config->http2.downstream.option,
config->http2.downstream.encoder_dynamic_table_size);
return 0;
case SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE:
return parse_uint_with_unit(
&config->http2.downstream.decoder_dynamic_table_size, opt, optarg);
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";

View File

@ -299,6 +299,14 @@ constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE =
StringRef::from_lit("backend-http2-window-size"); StringRef::from_lit("backend-http2-window-size");
constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE = constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE =
StringRef::from_lit("backend-http2-connection-window-size"); StringRef::from_lit("backend-http2-connection-window-size");
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE =
StringRef::from_lit("frontend-http2-encoder-dynamic-table-size");
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE =
StringRef::from_lit("frontend-http2-decoder-dynamic-table-size");
constexpr auto SHRPX_OPT_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE =
StringRef::from_lit("backend-http2-encoder-dynamic-table-size");
constexpr auto SHRPX_OPT_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE =
StringRef::from_lit("backend-http2-decoder-dynamic-table-size");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -595,9 +603,11 @@ struct Http2Config {
nghttp2_option *option; nghttp2_option *option;
nghttp2_option *alt_mode_option; nghttp2_option *alt_mode_option;
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
size_t max_concurrent_streams;
size_t encoder_dynamic_table_size;
size_t decoder_dynamic_table_size;
int32_t window_size; int32_t window_size;
int32_t connection_window_size; int32_t connection_window_size;
size_t max_concurrent_streams;
bool optimize_write_buffer_size; bool optimize_write_buffer_size;
bool optimize_window_size; bool optimize_window_size;
} upstream; } upstream;
@ -607,6 +617,8 @@ struct Http2Config {
} timeout; } timeout;
nghttp2_option *option; nghttp2_option *option;
nghttp2_session_callbacks *callbacks; nghttp2_session_callbacks *callbacks;
size_t encoder_dynamic_table_size;
size_t decoder_dynamic_table_size;
int32_t window_size; int32_t window_size;
int32_t connection_window_size; int32_t connection_window_size;
size_t max_concurrent_streams; size_t max_concurrent_streams;
@ -795,6 +807,8 @@ enum {
SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS, SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS,
SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE, SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE,
SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER, SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER,
SHRPX_OPTID_BACKEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
SHRPX_OPTID_BACKEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS, SHRPX_OPTID_BACKEND_HTTP2_MAX_CONCURRENT_STREAMS,
SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT, SHRPX_OPTID_BACKEND_HTTP2_SETTINGS_TIMEOUT,
SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS, SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS,
@ -832,8 +846,10 @@ enum {
SHRPX_OPTID_FRONTEND_FRAME_DEBUG, SHRPX_OPTID_FRONTEND_FRAME_DEBUG,
SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS, SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS,
SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE, SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE,
SHRPX_OPTID_FRONTEND_HTTP2_DECODER_DYNAMIC_TABLE_SIZE,
SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER, SHRPX_OPTID_FRONTEND_HTTP2_DUMP_REQUEST_HEADER,
SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER, SHRPX_OPTID_FRONTEND_HTTP2_DUMP_RESPONSE_HEADER,
SHRPX_OPTID_FRONTEND_HTTP2_ENCODER_DYNAMIC_TABLE_SIZE,
SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS, SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS,
SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE, SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE,
SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE, SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE,

View File

@ -1584,7 +1584,7 @@ int Http2Session::connection_made() {
return -1; return -1;
} }
std::array<nghttp2_settings_entry, 3> entry; std::array<nghttp2_settings_entry, 4> entry;
size_t nentry = 2; size_t nentry = 2;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = http2conf.downstream.max_concurrent_streams; entry[0].value = http2conf.downstream.max_concurrent_streams;
@ -1598,6 +1598,13 @@ int Http2Session::connection_made() {
++nentry; ++nentry;
} }
if (http2conf.downstream.decoder_dynamic_table_size !=
NGHTTP2_DEFAULT_HEADER_TABLE_SIZE) {
entry[nentry].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
entry[nentry].value = http2conf.downstream.decoder_dynamic_table_size;
++nentry;
}
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
nentry); nentry);
if (rv != 0) { if (rv != 0) {

View File

@ -939,7 +939,9 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
flow_control_ = true; flow_control_ = true;
// TODO Maybe call from outside? // TODO Maybe call from outside?
std::array<nghttp2_settings_entry, 2> entry; std::array<nghttp2_settings_entry, 3> entry;
size_t nentry = 2;
entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; entry[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
entry[0].value = http2conf.upstream.max_concurrent_streams; entry[0].value = http2conf.upstream.max_concurrent_streams;
@ -950,8 +952,15 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
entry[1].value = http2conf.upstream.window_size; entry[1].value = http2conf.upstream.window_size;
} }
if (http2conf.upstream.decoder_dynamic_table_size !=
NGHTTP2_DEFAULT_HEADER_TABLE_SIZE) {
entry[nentry].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
entry[nentry].value = http2conf.upstream.decoder_dynamic_table_size;
++nentry;
}
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(), rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
entry.size()); nentry);
if (rv != 0) { if (rv != 0) {
ULOG(ERROR, this) << "nghttp2_submit_settings() returned error: " ULOG(ERROR, this) << "nghttp2_submit_settings() returned error: "
<< nghttp2_strerror(rv); << nghttp2_strerror(rv);