Follow up to r1836032: better flush limits checks and description.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1884304 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yann Ylavic
2020-12-11 11:33:00 +00:00
parent 4e4cf19efe
commit 2bc917d4e9
4 changed files with 45 additions and 36 deletions

View File

@ -2031,21 +2031,24 @@ filenames</description>
<directivesynopsis> <directivesynopsis>
<name>FlushMaxPipelined</name> <name>FlushMaxPipelined</name>
<description>Threshold above which pipelined responses are flushed to the <description>Maximum number of pipelined responses above which they are flushed
network</description> to the network</description>
<syntax>FlushMaxPipelined <var>number</var></syntax> <syntax>FlushMaxPipelined <var>number</var></syntax>
<default>FlushMaxPipelined 5</default> <default>FlushMaxPipelined 5</default>
<contextlist><context>server config</context><context>virtual host</context> <contextlist><context>server config</context><context>virtual host</context>
<context>directory</context></contextlist> </contextlist>
<compatibility>2.5 and later</compatibility> <compatibility>2.5 and later</compatibility>
<usage> <usage>
<p>This directive allows to configure the threshold for pipelined <p>This directive allows to configure the maximum number of pipelined
responses, which remain pending so long as pipelined request are handled. responses, which remain pending so long as pipelined request are received.
When this limit is reached, are forcibly flushed to the network in blocking When the limit is reached, reponses are forcibly flushed to the network in
mode, until passing under the threshold again.</p> blocking mode, until passing under the limit again.</p>
<p>This threshold helps maintaning constrained memory usage.</p> <p><directive>FlushMaxPipelined</directive> helps constraining memory
usage. When set to <var>0</var> pipelining is disabled, when set to
<var>-1</var> there is no limit (<directive>FlushMaxThreshold</directive>
still applies).</p>
</usage> </usage>
</directivesynopsis> </directivesynopsis>
@ -2056,15 +2059,19 @@ network</description>
<syntax>FlushMaxThreshold<var>number-of-bytes</var></syntax> <syntax>FlushMaxThreshold<var>number-of-bytes</var></syntax>
<default>FlushMaxThreshold 65536</default> <default>FlushMaxThreshold 65536</default>
<contextlist><context>server config</context><context>virtual host</context> <contextlist><context>server config</context><context>virtual host</context>
<context>directory</context></contextlist> </contextlist>
<compatibility>2.5 and later</compatibility> <compatibility>2.5 and later</compatibility>
<usage> <usage>
<p>This directive allows to configure the threshold (in bytes) for pending <p>This directive allows to configure the threshold for pending output
output data. When this limit is reached, data are forcibly flushed to the data (in bytes). When the limit is reached, data are forcibly flushed to
network in blocking mode, until passing under the threshold again.</p> the network in blocking mode, until passing under the limit again.</p>
<p>This threshold helps maintaning constrained memory usage.</p> <p><directive>FlushMaxThreshold</directive> helps constraining memory
usage. When set to <var>0</var> or a too small value there are actually
no pending data, but for threaded MPMs there can be more threads busy
waiting for the network thus less ones available to handle the other
simultaneous connections.</p>
</usage> </usage>
</directivesynopsis> </directivesynopsis>
@ -4179,19 +4186,20 @@ Protocols h2 http/1.1
<directivesynopsis> <directivesynopsis>
<name>ReadBufferSize</name> <name>ReadBufferSize</name>
<description>Size of the buffers used to read network data</description> <description>Size of the buffers used to read data</description>
<syntax>ReadBufferSize <var>number-of-bytes</var></syntax> <syntax>ReadBufferSize <var>bytes</var></syntax>
<default>ReadBufferSize 8192</default> <default>ReadBufferSize 8192</default>
<contextlist><context>server config</context><context>virtual host</context> <contextlist><context>server config</context><context>virtual host</context>
<context>directory</context></contextlist> <context>directory</context></contextlist>
<compatibility>2.5 and later</compatibility> <compatibility>2.5 and later</compatibility>
<usage> <usage>
<p>This directive allows to configure the size in bytes of the memory <p>This directive allows to configure the size (in bytes) of the memory
buffers used to read data from the network.</p> buffer used to read data from the network or files.</p>
<p>Larger buffer can increase peformances for large data but consume more <p>A larger buffer can increase peformances with larger data, but consumes
memory (per connection).</p> more memory per connection. The minimum configurable size is
<var>1024</var>.</p>
</usage> </usage>
</directivesynopsis> </directivesynopsis>

View File

@ -83,8 +83,8 @@
/* valid in core-conf, but not in runtime r->used_path_info */ /* valid in core-conf, but not in runtime r->used_path_info */
#define AP_ACCEPT_PATHINFO_UNSET 3 #define AP_ACCEPT_PATHINFO_UNSET 3
#define AP_FLUSH_MAX_THRESHOLD 65536 #define AP_FLUSH_MAX_THRESHOLD 65535
#define AP_FLUSH_MAX_PIPELINED 5 #define AP_FLUSH_MAX_PIPELINED 4
APR_HOOK_STRUCT( APR_HOOK_STRUCT(
APR_HOOK_LINK(get_mgmt_items) APR_HOOK_LINK(get_mgmt_items)
@ -2344,10 +2344,10 @@ static const char *set_read_buf_size(cmd_parms *cmd, void *d_,
char *end; char *end;
if (apr_strtoff(&size, arg, &end, 10) if (apr_strtoff(&size, arg, &end, 10)
|| size < 0 || size > APR_SIZE_MAX || *end) || *end || size < 0 || size > APR_UINT32_MAX)
return apr_pstrcat(cmd->pool, return apr_pstrcat(cmd->pool,
"parameter must be a number between 0 and " "parameter must be a number between 0 and "
APR_STRINGIFY(APR_SIZE_MAX) "): ", APR_STRINGIFY(APR_UINT32_MAX) "): ",
arg, NULL); arg, NULL);
d->read_buf_size = (apr_size_t)size; d->read_buf_size = (apr_size_t)size;
@ -2364,10 +2364,10 @@ static const char *set_flush_max_threshold(cmd_parms *cmd, void *d_,
char *end; char *end;
if (apr_strtoff(&size, arg, &end, 10) if (apr_strtoff(&size, arg, &end, 10)
|| size <= 0 || size > APR_SIZE_MAX || *end) || *end || size < 0 || size > APR_UINT32_MAX)
return apr_pstrcat(cmd->pool, return apr_pstrcat(cmd->pool,
"parameter must be a number between 1 and " "parameter must be a number between 0 and "
APR_STRINGIFY(APR_SIZE_MAX) "): ", APR_STRINGIFY(APR_UINT32_MAX) "): ",
arg, NULL); arg, NULL);
conf->flush_max_threshold = (apr_size_t)size; conf->flush_max_threshold = (apr_size_t)size;
@ -2384,9 +2384,9 @@ static const char *set_flush_max_pipelined(cmd_parms *cmd, void *d_,
char *end; char *end;
if (apr_strtoff(&num, arg, &end, 10) if (apr_strtoff(&num, arg, &end, 10)
|| num < 0 || num > APR_INT32_MAX || *end) || *end || num < -1 || num > APR_INT32_MAX)
return apr_pstrcat(cmd->pool, return apr_pstrcat(cmd->pool,
"parameter must be a number between 0 and " "parameter must be a number between -1 and "
APR_STRINGIFY(APR_INT32_MAX) ": ", APR_STRINGIFY(APR_INT32_MAX) ": ",
arg, NULL); arg, NULL);
@ -2395,7 +2395,6 @@ static const char *set_flush_max_pipelined(cmd_parms *cmd, void *d_,
return NULL; return NULL;
} }
/* /*
* Report a missing-'>' syntax error. * Report a missing-'>' syntax error.
*/ */
@ -4733,9 +4732,10 @@ AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO,
AP_INIT_TAKE1("ReadBufferSize", set_read_buf_size, NULL, ACCESS_CONF|RSRC_CONF, AP_INIT_TAKE1("ReadBufferSize", set_read_buf_size, NULL, ACCESS_CONF|RSRC_CONF,
"Size (in bytes) of the memory buffers used to read data"), "Size (in bytes) of the memory buffers used to read data"),
AP_INIT_TAKE1("FlushMaxThreshold", set_flush_max_threshold, NULL, RSRC_CONF, AP_INIT_TAKE1("FlushMaxThreshold", set_flush_max_threshold, NULL, RSRC_CONF,
"Maximum size (in bytes) above which pending data are flushed (blocking) to the network"), "Maximum threshold above which pending data are flushed to the network"),
AP_INIT_TAKE1("FlushMaxPipelined", set_flush_max_pipelined, NULL, RSRC_CONF, AP_INIT_TAKE1("FlushMaxPipelined", set_flush_max_pipelined, NULL, RSRC_CONF,
"Number of pipelined/pending responses above which they are flushed to the network"), "Maximum number of pipelined responses (pending) above which they are "
"flushed to the network"),
/* Old server config file commands */ /* Old server config file commands */

View File

@ -610,7 +610,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
* we are at the end of the brigade, the write will happen outside * we are at the end of the brigade, the write will happen outside
* the loop anyway). * the loop anyway).
*/ */
if (nbytes >= conf->flush_max_threshold if (nbytes > conf->flush_max_threshold
&& next != APR_BRIGADE_SENTINEL(bb) && next != APR_BRIGADE_SENTINEL(bb)
&& !is_in_memory_bucket(next)) { && !is_in_memory_bucket(next)) {
(void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1); (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);

View File

@ -1104,7 +1104,7 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f,
* sent to the client.) * sent to the client.)
* *
* c) The brigade contains at least flush_max_pipelined EOR buckets: do * c) The brigade contains at least flush_max_pipelined EOR buckets: do
* blocking writes until the last EOR above flush_max_pipelined. * blocking writes until after the last EOR above flush_max_pipelined.
* (The point of this rule is to prevent too many FDs being kept open * (The point of this rule is to prevent too many FDs being kept open
* by pipelined requests, possibly allowing a DoS). * by pipelined requests, possibly allowing a DoS).
* *
@ -1140,14 +1140,15 @@ AP_DECLARE(apr_status_t) ap_filter_reinstate_brigade(ap_filter_t *f,
} }
if (APR_BUCKET_IS_FLUSH(bucket) if (APR_BUCKET_IS_FLUSH(bucket)
|| memory_bytes_in_brigade >= conf->flush_max_threshold || (memory_bytes_in_brigade > conf->flush_max_threshold)
|| eor_buckets_in_brigade >= conf->flush_max_pipelined) { || (conf->flush_max_pipelined >= 0
&& eor_buckets_in_brigade > conf->flush_max_pipelined)) {
/* this segment of the brigade MUST be sent before returning. */ /* this segment of the brigade MUST be sent before returning. */
if (APLOGctrace6(f->c)) { if (APLOGctrace6(f->c)) {
char *reason = APR_BUCKET_IS_FLUSH(bucket) ? char *reason = APR_BUCKET_IS_FLUSH(bucket) ?
"FLUSH bucket" : "FLUSH bucket" :
(memory_bytes_in_brigade >= conf->flush_max_threshold) ? (memory_bytes_in_brigade > conf->flush_max_threshold) ?
"max threshold" : "max requests in pipeline"; "max threshold" : "max requests in pipeline";
ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c, ap_log_cerror(APLOG_MARK, APLOG_TRACE6, 0, f->c,
"will flush because of %s", reason); "will flush because of %s", reason);