nghttpx: Add --frontend-http2-window-size option, and its family
We added --frontend-http2-window-size, --frontend-http2-connection-window-size, --backend-http2-window-size, and --backend-http2-connection-window-size option to replace existing *-bits options. The old options are not flexible because they only specify number of bits. Now we can specify integer value, with possible g, m, and k unit. The old options are still available for backend compatibility, but are deprecated.
This commit is contained in:
parent
27b250ac8e
commit
f5a2f1da25
|
@ -138,6 +138,10 @@ OPTIONS = [
|
||||||
"no-server-rewrite",
|
"no-server-rewrite",
|
||||||
"frontend-http2-optimize-write-buffer-size",
|
"frontend-http2-optimize-write-buffer-size",
|
||||||
"frontend-http2-optimize-window-size",
|
"frontend-http2-optimize-window-size",
|
||||||
|
"frontend-http2-window-size",
|
||||||
|
"frontend-http2-connection-window-size",
|
||||||
|
"backend-http2-window-size",
|
||||||
|
"backend-http2-connection-window-size",
|
||||||
]
|
]
|
||||||
|
|
||||||
LOGVARS = [
|
LOGVARS = [
|
||||||
|
|
80
src/shrpx.cc
80
src/shrpx.cc
|
@ -1335,13 +1335,14 @@ void fill_default_config(Config *config) {
|
||||||
timeoutconf.settings = 10_s;
|
timeoutconf.settings = 10_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
// window bits for HTTP/2 and SPDY upstream connection per
|
// window size for HTTP/2 and SPDY upstream connection per stream.
|
||||||
// stream. 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note
|
// 2**16-1 = 64KiB-1, which is HTTP/2 default. Please note that
|
||||||
// that SPDY/3 default is 64KiB.
|
// SPDY/3 default is 64KiB.
|
||||||
upstreamconf.window_bits = 16;
|
upstreamconf.window_size = 64_k - 1;
|
||||||
// HTTP/2 SPDY/3.1 has connection-level flow control. The default
|
// HTTP/2 and SPDY/3.1 has connection-level flow control. The
|
||||||
// window size for HTTP/2 is 64KiB - 1. SPDY/3's default is 64KiB
|
// default window size for HTTP/2 is 64KiB - 1. SPDY/3's default
|
||||||
upstreamconf.connection_window_bits = 16;
|
// is 64KiB
|
||||||
|
upstreamconf.connection_window_size = 64_k - 1;
|
||||||
upstreamconf.max_concurrent_streams = 100;
|
upstreamconf.max_concurrent_streams = 100;
|
||||||
|
|
||||||
nghttp2_option_new(&upstreamconf.option);
|
nghttp2_option_new(&upstreamconf.option);
|
||||||
|
@ -1362,8 +1363,8 @@ void fill_default_config(Config *config) {
|
||||||
timeoutconf.settings = 10_s;
|
timeoutconf.settings = 10_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
downstreamconf.window_bits = 16;
|
downstreamconf.window_size = 64_k - 1;
|
||||||
downstreamconf.connection_window_bits = 30;
|
downstreamconf.connection_window_size = (1u << 31) - 1;
|
||||||
downstreamconf.max_concurrent_streams = 100;
|
downstreamconf.max_concurrent_streams = 100;
|
||||||
|
|
||||||
nghttp2_option_new(&downstreamconf.option);
|
nghttp2_option_new(&downstreamconf.option);
|
||||||
|
@ -1997,26 +1998,25 @@ HTTP/2 and SPDY:
|
||||||
concurrent requests are set by a remote server.
|
concurrent requests are set by a remote server.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< get_config()->http2.downstream.max_concurrent_streams << R"(
|
<< get_config()->http2.downstream.max_concurrent_streams << R"(
|
||||||
--frontend-http2-window-bits=<N>
|
--frontend-http2-window-size=<SIZE>
|
||||||
Sets the per-stream initial window size of HTTP/2 SPDY
|
Sets the per-stream initial window size of HTTP/2 and
|
||||||
frontend connection. For HTTP/2, the size is 2**<N>-1.
|
SPDY frontend connection.
|
||||||
For SPDY, the size is 2**<N>.
|
Default: )" << get_config()->http2.upstream.window_size << R"(
|
||||||
Default: )" << get_config()->http2.upstream.window_bits << R"(
|
--frontend-http2-connection-window-size=<SIZE>
|
||||||
--frontend-http2-connection-window-bits=<N>
|
|
||||||
Sets the per-connection window size of HTTP/2 and SPDY
|
Sets the per-connection window size of HTTP/2 and SPDY
|
||||||
frontend connection. For HTTP/2, the size is
|
frontend connection. For SPDY connection, the value
|
||||||
2**<N>-1. For SPDY, the size is 2**<N>.
|
less than 64KiB is rounded up to 64KiB.
|
||||||
Default: )" << get_config()->http2.upstream.connection_window_bits
|
Default: )" << get_config()->http2.upstream.connection_window_size
|
||||||
<< R"(
|
<< R"(
|
||||||
--backend-http2-window-bits=<N>
|
--backend-http2-window-size=<SIZE>
|
||||||
Sets the initial window size of HTTP/2 backend
|
Sets the initial window size of HTTP/2 backend
|
||||||
connection to 2**<N>-1.
|
connection.
|
||||||
Default: )" << get_config()->http2.downstream.window_bits << R"(
|
Default: )" << get_config()->http2.downstream.window_size << R"(
|
||||||
--backend-http2-connection-window-bits=<N>
|
--backend-http2-connection-window-size=<SIZE>
|
||||||
Sets the per-connection window size of HTTP/2 backend
|
Sets the per-connection window size of HTTP/2 backend
|
||||||
connection to 2**<N>-1.
|
connection.
|
||||||
Default: )"
|
Default: )"
|
||||||
<< get_config()->http2.downstream.connection_window_bits << R"(
|
<< get_config()->http2.downstream.connection_window_size << R"(
|
||||||
--http2-no-cookie-crumbling
|
--http2-no-cookie-crumbling
|
||||||
Don't crumble cookie header field.
|
Don't crumble cookie header field.
|
||||||
--padding=<N>
|
--padding=<N>
|
||||||
|
@ -2048,9 +2048,9 @@ HTTP/2 and SPDY:
|
||||||
automatically adjusts connection window size based on
|
automatically adjusts connection window size based on
|
||||||
TCP receiving window size. The maximum window size is
|
TCP receiving window size. The maximum window size is
|
||||||
capped by the value specified by
|
capped by the value specified by
|
||||||
--frontend-http2-connection-window-bits. Since the
|
--frontend-http2-connection-window-size. Since the
|
||||||
stream is subject to stream level window size, it should
|
stream is subject to stream level window size, it should
|
||||||
be adjusted using --frontend-http2-window-bits 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.
|
||||||
|
|
||||||
|
@ -2867,6 +2867,14 @@ int main(int argc, char **argv) {
|
||||||
no_argument, &flag, 130},
|
no_argument, &flag, 130},
|
||||||
{SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.c_str(), no_argument,
|
{SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE.c_str(), no_argument,
|
||||||
&flag, 131},
|
&flag, 131},
|
||||||
|
{SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
|
||||||
|
132},
|
||||||
|
{SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
|
||||||
|
required_argument, &flag, 133},
|
||||||
|
{SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE.c_str(), required_argument, &flag,
|
||||||
|
134},
|
||||||
|
{SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE.c_str(),
|
||||||
|
required_argument, &flag, 135},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
|
|
||||||
int option_index = 0;
|
int option_index = 0;
|
||||||
|
@ -3484,6 +3492,26 @@ int main(int argc, char **argv) {
|
||||||
cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE,
|
cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE,
|
||||||
StringRef::from_lit("yes"));
|
StringRef::from_lit("yes"));
|
||||||
break;
|
break;
|
||||||
|
case 132:
|
||||||
|
// --frontend-http2-window-size
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE,
|
||||||
|
StringRef{optarg});
|
||||||
|
break;
|
||||||
|
case 133:
|
||||||
|
// --frontend-http2-connection-window-size
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE,
|
||||||
|
StringRef{optarg});
|
||||||
|
break;
|
||||||
|
case 134:
|
||||||
|
// --backend-http2-window-size
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE,
|
||||||
|
StringRef{optarg});
|
||||||
|
break;
|
||||||
|
case 135:
|
||||||
|
// --backend-http2-connection-window-size
|
||||||
|
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE,
|
||||||
|
StringRef{optarg});
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -320,6 +320,13 @@ int parse_uint_with_unit(T *dest, const StringRef &opt,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::max() < n) {
|
||||||
|
LOG(ERROR) << opt
|
||||||
|
<< ": too large. The value should be less than or equal to "
|
||||||
|
<< std::numeric_limits<T>::max();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
*dest = n;
|
*dest = n;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1482,6 +1489,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 25:
|
||||||
switch (name[24]) {
|
switch (name[24]) {
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("backend-http2-window-siz", name, 24)) {
|
||||||
|
return SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'g':
|
case 'g':
|
||||||
if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) {
|
if (util::strieq_l("http2-no-cookie-crumblin", name, 24)) {
|
||||||
return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING;
|
return SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING;
|
||||||
|
@ -1499,6 +1511,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
break;
|
break;
|
||||||
case 26:
|
case 26:
|
||||||
switch (name[25]) {
|
switch (name[25]) {
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("frontend-http2-window-siz", name, 25)) {
|
||||||
|
return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if (util::strieq_l("frontend-http2-window-bit", name, 25)) {
|
if (util::strieq_l("frontend-http2-window-bit", name, 25)) {
|
||||||
return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS;
|
return SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS;
|
||||||
|
@ -1657,6 +1674,11 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
break;
|
break;
|
||||||
case 36:
|
case 36:
|
||||||
switch (name[35]) {
|
switch (name[35]) {
|
||||||
|
case 'e':
|
||||||
|
if (util::strieq_l("backend-http2-connection-window-siz", name, 35)) {
|
||||||
|
return SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) {
|
if (util::strieq_l("backend-http2-connections-per-worke", name, 35)) {
|
||||||
return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER;
|
return SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER;
|
||||||
|
@ -1675,6 +1697,9 @@ int option_lookup_token(const char *name, size_t namelen) {
|
||||||
case 37:
|
case 37:
|
||||||
switch (name[36]) {
|
switch (name[36]) {
|
||||||
case 'e':
|
case 'e':
|
||||||
|
if (util::strieq_l("frontend-http2-connection-window-siz", name, 36)) {
|
||||||
|
return SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE;
|
||||||
|
}
|
||||||
if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) {
|
if (util::strieq_l("tls-session-cache-memcached-cert-fil", name, 36)) {
|
||||||
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE;
|
return SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED_CERT_FILE;
|
||||||
}
|
}
|
||||||
|
@ -1964,12 +1989,16 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
optarg);
|
optarg);
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
|
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS:
|
||||||
case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: {
|
case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_BITS: {
|
||||||
size_t *resp;
|
LOG(WARN) << opt << ": deprecated. Use "
|
||||||
|
<< (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS
|
||||||
|
? SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE
|
||||||
|
: SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE);
|
||||||
|
int32_t *resp;
|
||||||
|
|
||||||
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
|
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS) {
|
||||||
resp = &config->http2.upstream.window_bits;
|
resp = &config->http2.upstream.window_size;
|
||||||
} else {
|
} else {
|
||||||
resp = &config->http2.downstream.window_bits;
|
resp = &config->http2.downstream.window_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -1986,18 +2015,25 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*resp = n;
|
// Make 16 bits to the HTTP/2 default 64KiB - 1. This is the same
|
||||||
|
// behaviour of previous code. For SPDY, we adjust this value in
|
||||||
|
// SpdyUpstream to look like the SPDY default.
|
||||||
|
*resp = (1 << n) - 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS:
|
case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS:
|
||||||
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS: {
|
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_BITS: {
|
||||||
size_t *resp;
|
LOG(WARN) << opt << ": deprecated. Use "
|
||||||
|
<< (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS
|
||||||
|
? SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE
|
||||||
|
: SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE);
|
||||||
|
int32_t *resp;
|
||||||
|
|
||||||
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
|
if (optid == SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_BITS) {
|
||||||
resp = &config->http2.upstream.connection_window_bits;
|
resp = &config->http2.upstream.connection_window_size;
|
||||||
} else {
|
} else {
|
||||||
resp = &config->http2.downstream.connection_window_bits;
|
resp = &config->http2.downstream.connection_window_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
@ -2014,7 +2050,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*resp = n;
|
*resp = (1 << n) - 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2707,6 +2743,34 @@ int parse_config(Config *config, int optid, const StringRef &opt,
|
||||||
case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE:
|
case SHRPX_OPTID_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE:
|
||||||
config->http2.upstream.optimize_window_size = util::strieq_l("yes", optarg);
|
config->http2.upstream.optimize_window_size = util::strieq_l("yes", optarg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE:
|
||||||
|
if (parse_uint_with_unit(&config->http2.upstream.window_size, opt,
|
||||||
|
optarg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE:
|
||||||
|
if (parse_uint_with_unit(&config->http2.upstream.connection_window_size,
|
||||||
|
opt, optarg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE:
|
||||||
|
if (parse_uint_with_unit(&config->http2.downstream.window_size, opt,
|
||||||
|
optarg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
case SHRPX_OPTID_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE:
|
||||||
|
if (parse_uint_with_unit(&config->http2.downstream.connection_window_size,
|
||||||
|
opt, optarg) != 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
case SHRPX_OPTID_CONF:
|
case SHRPX_OPTID_CONF:
|
||||||
LOG(WARN) << "conf: ignored";
|
LOG(WARN) << "conf: ignored";
|
||||||
|
|
|
@ -291,6 +291,14 @@ constexpr auto SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WRITE_BUFFER_SIZE =
|
||||||
StringRef::from_lit("frontend-http2-optimize-write-buffer-size");
|
StringRef::from_lit("frontend-http2-optimize-write-buffer-size");
|
||||||
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE =
|
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_OPTIMIZE_WINDOW_SIZE =
|
||||||
StringRef::from_lit("frontend-http2-optimize-window-size");
|
StringRef::from_lit("frontend-http2-optimize-window-size");
|
||||||
|
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_WINDOW_SIZE =
|
||||||
|
StringRef::from_lit("frontend-http2-window-size");
|
||||||
|
constexpr auto SHRPX_OPT_FRONTEND_HTTP2_CONNECTION_WINDOW_SIZE =
|
||||||
|
StringRef::from_lit("frontend-http2-connection-window-size");
|
||||||
|
constexpr auto SHRPX_OPT_BACKEND_HTTP2_WINDOW_SIZE =
|
||||||
|
StringRef::from_lit("backend-http2-window-size");
|
||||||
|
constexpr auto SHRPX_OPT_BACKEND_HTTP2_CONNECTION_WINDOW_SIZE =
|
||||||
|
StringRef::from_lit("backend-http2-connection-window-size");
|
||||||
|
|
||||||
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
|
||||||
|
|
||||||
|
@ -587,8 +595,8 @@ 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 window_bits;
|
int32_t window_size;
|
||||||
size_t connection_window_bits;
|
int32_t connection_window_size;
|
||||||
size_t max_concurrent_streams;
|
size_t max_concurrent_streams;
|
||||||
bool optimize_write_buffer_size;
|
bool optimize_write_buffer_size;
|
||||||
bool optimize_window_size;
|
bool optimize_window_size;
|
||||||
|
@ -599,8 +607,8 @@ struct Http2Config {
|
||||||
} timeout;
|
} timeout;
|
||||||
nghttp2_option *option;
|
nghttp2_option *option;
|
||||||
nghttp2_session_callbacks *callbacks;
|
nghttp2_session_callbacks *callbacks;
|
||||||
size_t window_bits;
|
int32_t window_size;
|
||||||
size_t connection_window_bits;
|
int32_t connection_window_size;
|
||||||
size_t max_concurrent_streams;
|
size_t max_concurrent_streams;
|
||||||
} downstream;
|
} downstream;
|
||||||
struct {
|
struct {
|
||||||
|
@ -785,10 +793,12 @@ enum {
|
||||||
SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST,
|
SHRPX_OPTID_BACKEND_HTTP1_CONNECTIONS_PER_HOST,
|
||||||
SHRPX_OPTID_BACKEND_HTTP1_TLS,
|
SHRPX_OPTID_BACKEND_HTTP1_TLS,
|
||||||
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_CONNECTIONS_PER_WORKER,
|
SHRPX_OPTID_BACKEND_HTTP2_CONNECTIONS_PER_WORKER,
|
||||||
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,
|
||||||
|
SHRPX_OPTID_BACKEND_HTTP2_WINDOW_SIZE,
|
||||||
SHRPX_OPTID_BACKEND_IPV4,
|
SHRPX_OPTID_BACKEND_IPV4,
|
||||||
SHRPX_OPTID_BACKEND_IPV6,
|
SHRPX_OPTID_BACKEND_IPV6,
|
||||||
SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT,
|
SHRPX_OPTID_BACKEND_KEEP_ALIVE_TIMEOUT,
|
||||||
|
@ -821,6 +831,7 @@ enum {
|
||||||
SHRPX_OPTID_FRONTEND,
|
SHRPX_OPTID_FRONTEND,
|
||||||
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_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_MAX_CONCURRENT_STREAMS,
|
SHRPX_OPTID_FRONTEND_HTTP2_MAX_CONCURRENT_STREAMS,
|
||||||
|
@ -829,6 +840,7 @@ enum {
|
||||||
SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT,
|
SHRPX_OPTID_FRONTEND_HTTP2_READ_TIMEOUT,
|
||||||
SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT,
|
SHRPX_OPTID_FRONTEND_HTTP2_SETTINGS_TIMEOUT,
|
||||||
SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS,
|
SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_BITS,
|
||||||
|
SHRPX_OPTID_FRONTEND_HTTP2_WINDOW_SIZE,
|
||||||
SHRPX_OPTID_FRONTEND_NO_TLS,
|
SHRPX_OPTID_FRONTEND_NO_TLS,
|
||||||
SHRPX_OPTID_FRONTEND_READ_TIMEOUT,
|
SHRPX_OPTID_FRONTEND_READ_TIMEOUT,
|
||||||
SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT,
|
SHRPX_OPTID_FRONTEND_WRITE_TIMEOUT,
|
||||||
|
|
|
@ -1590,7 +1590,7 @@ int Http2Session::connection_made() {
|
||||||
entry[0].value = http2conf.downstream.max_concurrent_streams;
|
entry[0].value = http2conf.downstream.max_concurrent_streams;
|
||||||
|
|
||||||
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
entry[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||||
entry[1].value = (1 << http2conf.downstream.window_bits) - 1;
|
entry[1].value = http2conf.downstream.window_size;
|
||||||
|
|
||||||
if (http2conf.no_server_push || get_config()->http2_proxy) {
|
if (http2conf.no_server_push || get_config()->http2_proxy) {
|
||||||
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
|
entry[nentry].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH;
|
||||||
|
@ -1604,14 +1604,11 @@ int Http2Session::connection_made() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (http2conf.downstream.connection_window_bits != 16) {
|
rv = nghttp2_session_set_local_window_size(
|
||||||
int32_t window_size =
|
session_, NGHTTP2_FLAG_NONE, 0,
|
||||||
(1 << http2conf.downstream.connection_window_bits) - 1;
|
http2conf.downstream.connection_window_size);
|
||||||
rv = nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0,
|
if (rv != 0) {
|
||||||
window_size);
|
return -1;
|
||||||
if (rv != 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto must_terminate =
|
auto must_terminate =
|
||||||
|
|
|
@ -947,7 +947,7 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
if (faddr->alt_mode) {
|
if (faddr->alt_mode) {
|
||||||
entry[1].value = (1u << 31) - 1;
|
entry[1].value = (1u << 31) - 1;
|
||||||
} else {
|
} else {
|
||||||
entry[1].value = (1 << http2conf.upstream.window_bits) - 1;
|
entry[1].value = http2conf.upstream.window_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
|
rv = nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, entry.data(),
|
||||||
|
@ -957,20 +957,17 @@ Http2Upstream::Http2Upstream(ClientHandler *handler)
|
||||||
<< nghttp2_strerror(rv);
|
<< nghttp2_strerror(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t window_bits =
|
auto window_size = faddr->alt_mode
|
||||||
faddr->alt_mode ? 31 : http2conf.upstream.optimize_window_size
|
? std::numeric_limits<int32_t>::max()
|
||||||
? 16
|
: http2conf.upstream.connection_window_size;
|
||||||
: http2conf.upstream.connection_window_bits;
|
|
||||||
|
|
||||||
if (window_bits != 16) {
|
rv = nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0,
|
||||||
int32_t window_size = (1u << window_bits) - 1;
|
window_size);
|
||||||
rv = nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0,
|
|
||||||
window_size);
|
|
||||||
|
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
ULOG(ERROR, this) << "nghttp2_submit_window_update() returned error: "
|
ULOG(ERROR, this)
|
||||||
<< nghttp2_strerror(rv);
|
<< "nghttp2_session_set_local_window_size() returned error: "
|
||||||
}
|
<< nghttp2_strerror(rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We wait for SETTINGS ACK at least 10 seconds.
|
// We wait for SETTINGS ACK at least 10 seconds.
|
||||||
|
@ -1073,10 +1070,8 @@ int Http2Upstream::on_write() {
|
||||||
if (http2conf.upstream.optimize_window_size) {
|
if (http2conf.upstream.optimize_window_size) {
|
||||||
auto faddr = handler_->get_upstream_addr();
|
auto faddr = handler_->get_upstream_addr();
|
||||||
if (!faddr->alt_mode) {
|
if (!faddr->alt_mode) {
|
||||||
int32_t window_size =
|
auto window_size = std::min(http2conf.upstream.connection_window_size,
|
||||||
(1u << http2conf.upstream.connection_window_bits) - 1;
|
static_cast<int32_t>(hint.rwin * 2));
|
||||||
window_size =
|
|
||||||
std::min(static_cast<uint32_t>(window_size), hint.rwin * 2);
|
|
||||||
|
|
||||||
rv = nghttp2_session_set_local_window_size(
|
rv = nghttp2_session_set_local_window_size(
|
||||||
session_, NGHTTP2_FLAG_NONE, 0, window_size);
|
session_, NGHTTP2_FLAG_NONE, 0, window_size);
|
||||||
|
|
|
@ -53,6 +53,28 @@ namespace {
|
||||||
constexpr size_t MAX_BUFFER_SIZE = 32_k;
|
constexpr size_t MAX_BUFFER_SIZE = 32_k;
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int32_t get_connection_window_size() {
|
||||||
|
return std::max(get_config()->http2.upstream.connection_window_size,
|
||||||
|
static_cast<int32_t>(64_k));
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
int32_t get_window_size() {
|
||||||
|
auto n = get_config()->http2.upstream.window_size;
|
||||||
|
|
||||||
|
// 65535 is the default window size of HTTP/2. OTOH, the default
|
||||||
|
// window size of SPDY is 65536. The configuration defaults to
|
||||||
|
// HTTP/2, so if we have 65535, we use 65536 for SPDY.
|
||||||
|
if (n == 65535) {
|
||||||
|
return 64_k;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t len,
|
ssize_t send_callback(spdylay_session *session, const uint8_t *data, size_t len,
|
||||||
int flags, void *user_data) {
|
int flags, void *user_data) {
|
||||||
|
@ -402,33 +424,27 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &http2conf = get_config()->http2;
|
|
||||||
|
|
||||||
// If connection-level window control is not enabled (e.g,
|
// If connection-level window control is not enabled (e.g,
|
||||||
// spdy/3), spdylay_session_get_recv_data_length() is always
|
// spdy/3), spdylay_session_get_recv_data_length() is always
|
||||||
// returns 0.
|
// returns 0.
|
||||||
if (spdylay_session_get_recv_data_length(session) >
|
if (spdylay_session_get_recv_data_length(session) >
|
||||||
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE, get_connection_window_size())) {
|
||||||
1 << http2conf.upstream.connection_window_bits)) {
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Flow control error on connection: "
|
ULOG(INFO, upstream) << "Flow control error on connection: "
|
||||||
<< "recv_window_size="
|
<< "recv_window_size="
|
||||||
<< spdylay_session_get_recv_data_length(session)
|
<< spdylay_session_get_recv_data_length(session)
|
||||||
<< ", window_size="
|
<< ", window_size=" << get_connection_window_size();
|
||||||
<< (1 << http2conf.upstream.connection_window_bits);
|
|
||||||
}
|
}
|
||||||
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
|
if (spdylay_session_get_stream_recv_data_length(session, stream_id) >
|
||||||
std::max(SPDYLAY_INITIAL_WINDOW_SIZE,
|
std::max(SPDYLAY_INITIAL_WINDOW_SIZE, get_window_size())) {
|
||||||
1 << http2conf.upstream.window_bits)) {
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
|
ULOG(INFO, upstream) << "Flow control error: recv_window_size="
|
||||||
<< spdylay_session_get_stream_recv_data_length(
|
<< spdylay_session_get_stream_recv_data_length(
|
||||||
session, stream_id)
|
session, stream_id)
|
||||||
<< ", initial_window_size="
|
<< ", initial_window_size=" << get_window_size();
|
||||||
<< (1 << http2conf.upstream.window_bits);
|
|
||||||
}
|
}
|
||||||
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
|
||||||
return;
|
return;
|
||||||
|
@ -574,16 +590,17 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
// going to be deprecated in the future, and the default stream
|
// going to be deprecated in the future, and the default stream
|
||||||
// window is large enough for API request body (64KiB), we don't
|
// window is large enough for API request body (64KiB), we don't
|
||||||
// expand window size depending on the options.
|
// expand window size depending on the options.
|
||||||
|
int32_t initial_window_size;
|
||||||
if (version >= SPDYLAY_PROTO_SPDY3 && !faddr->alt_mode) {
|
if (version >= SPDYLAY_PROTO_SPDY3 && !faddr->alt_mode) {
|
||||||
int val = 1;
|
int val = 1;
|
||||||
flow_control_ = true;
|
flow_control_ = true;
|
||||||
initial_window_size_ = 1 << http2conf.upstream.window_bits;
|
initial_window_size = get_window_size();
|
||||||
rv = spdylay_session_set_option(
|
rv = spdylay_session_set_option(
|
||||||
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
|
session_, SPDYLAY_OPT_NO_AUTO_WINDOW_UPDATE2, &val, sizeof(val));
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
} else {
|
} else {
|
||||||
flow_control_ = false;
|
flow_control_ = false;
|
||||||
initial_window_size_ = 0;
|
initial_window_size = 0;
|
||||||
}
|
}
|
||||||
// TODO Maybe call from outside?
|
// TODO Maybe call from outside?
|
||||||
std::array<spdylay_settings_entry, 2> entry;
|
std::array<spdylay_settings_entry, 2> entry;
|
||||||
|
@ -595,7 +612,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
if (flow_control_) {
|
if (flow_control_) {
|
||||||
++num_entry;
|
++num_entry;
|
||||||
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
|
entry[1].settings_id = SPDYLAY_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||||
entry[1].value = initial_window_size_;
|
entry[1].value = initial_window_size;
|
||||||
entry[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
entry[1].flags = SPDYLAY_ID_FLAG_SETTINGS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,10 +620,11 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||||
entry.data(), num_entry);
|
entry.data(), num_entry);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
|
auto connection_window_size = get_connection_window_size();
|
||||||
|
|
||||||
if (flow_control_ && version >= SPDYLAY_PROTO_SPDY3_1 &&
|
if (flow_control_ && version >= SPDYLAY_PROTO_SPDY3_1 &&
|
||||||
http2conf.upstream.connection_window_bits > 16) {
|
connection_window_size > 64_k) {
|
||||||
int32_t delta = (1 << http2conf.upstream.connection_window_bits) -
|
int32_t delta = connection_window_size - SPDYLAY_INITIAL_WINDOW_SIZE;
|
||||||
SPDYLAY_INITIAL_WINDOW_SIZE;
|
|
||||||
rv = spdylay_submit_window_update(session_, 0, delta);
|
rv = spdylay_submit_window_update(session_, 0, delta);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,6 @@ private:
|
||||||
DownstreamQueue downstream_queue_;
|
DownstreamQueue downstream_queue_;
|
||||||
ClientHandler *handler_;
|
ClientHandler *handler_;
|
||||||
spdylay_session *session_;
|
spdylay_session *session_;
|
||||||
int32_t initial_window_size_;
|
|
||||||
bool flow_control_;
|
bool flow_control_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue