From 122af0b5a79a60a7b563f75390be15a22432f9d5 Mon Sep 17 00:00:00 2001 From: Denis Kirillov Date: Thu, 26 Oct 2023 16:44:40 +0300 Subject: [PATCH] [#220] Support configuring web server timeout params Set IdleTimeout and ReadHeaderTimeout to `30s`. Signed-off-by: Denis Kirillov --- CHANGELOG.md | 1 + cmd/s3-gw/app.go | 4 ++++ cmd/s3-gw/app_settings.go | 13 +++++++++++++ config/config.env | 23 +++++++++++++++++++++++ config/config.yaml | 27 +++++++++++++++++++++++++++ docs/configuration.md | 19 +++++++++++++++++++ 6 files changed, 87 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3feaa20..59507d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ This document outlines major changes between releases. - Use gate key to form object owner (#175) - Apply placement policies and copies if there is at least one valid value (#168) - Generalise config param `use_default_xmlns_for_complete_multipart` to `use_default_xmlns` so that use default xmlns for all requests (#221) +- Set server IdleTimeout and ReadHeaderTimeout to `30s` and allow to configure them (#220) ### Removed - Drop `tree.service` param (now endpoints from `peers` section are used) (#133) diff --git a/cmd/s3-gw/app.go b/cmd/s3-gw/app.go index 069e8e0..71e9868 100644 --- a/cmd/s3-gw/app.go +++ b/cmd/s3-gw/app.go @@ -528,6 +528,10 @@ func (a *App) Serve(ctx context.Context) { srv := new(http.Server) srv.Handler = chiRouter srv.ErrorLog = zap.NewStdLog(a.log) + srv.ReadTimeout = a.cfg.GetDuration(cfgWebReadTimeout) + srv.ReadHeaderTimeout = a.cfg.GetDuration(cfgWebReadHeaderTimeout) + srv.WriteTimeout = a.cfg.GetDuration(cfgWebWriteTimeout) + srv.IdleTimeout = a.cfg.GetDuration(cfgWebIdleTimeout) a.startServices() diff --git a/cmd/s3-gw/app_settings.go b/cmd/s3-gw/app_settings.go index 0af9210..02114c7 100644 --- a/cmd/s3-gw/app_settings.go +++ b/cmd/s3-gw/app_settings.go @@ -40,6 +40,9 @@ const ( defaultMaxClientsDeadline = time.Second * 30 defaultSoftMemoryLimit = math.MaxInt64 + + defaultReadHeaderTimeout = 30 * time.Second + defaultIdleTimeout = 30 * time.Second ) var defaultCopiesNumbers = []uint32{0} @@ -134,6 +137,12 @@ const ( // Settings. cfgKludgeCompleteMultipartUploadKeepalive = "kludge.complete_multipart_keepalive" cfgKludgeBypassContentEncodingCheckInChunks = "kludge.bypass_content_encoding_check_in_chunks" + // Web. + cfgWebReadTimeout = "web.read_timeout" + cfgWebReadHeaderTimeout = "web.read_header_timeout" + cfgWebWriteTimeout = "web.write_timeout" + cfgWebIdleTimeout = "web.idle_timeout" + // Command line args. cmdHelp = "help" cmdVersion = "version" @@ -541,6 +550,10 @@ func newSettings() *viper.Viper { v.SetDefault(cfgKludgeCompleteMultipartUploadKeepalive, 10*time.Second) v.SetDefault(cfgKludgeBypassContentEncodingCheckInChunks, false) + // web + v.SetDefault(cfgWebReadHeaderTimeout, defaultReadHeaderTimeout) + v.SetDefault(cfgWebIdleTimeout, defaultIdleTimeout) + // Bind flags if err := bindFlags(v, flags); err != nil { panic(fmt.Errorf("bind flags: %w", err)) diff --git a/config/config.env b/config/config.env index 10736b3..1d4d500 100644 --- a/config/config.env +++ b/config/config.env @@ -152,3 +152,26 @@ S3_GW_TRACING_EXPORTER="otlp_grpc" S3_GW_RUNTIME_SOFT_MEMORY_LIMIT=1073741824 S3_GW_FEATURES_MD5_ENABLED=false + +# ReadTimeout is the maximum duration for reading the entire +# request, including the body. A zero or negative value means +# there will be no timeout. +S3_GW_WEB_READ_TIMEOUT=0 +# ReadHeaderTimeout is the amount of time allowed to read +# request headers. The connection's read deadline is reset +# after reading the headers and the Handler can decide what +# is considered too slow for the body. If ReadHeaderTimeout +# is zero, the value of ReadTimeout is used. If both are +# zero, there is no timeout. +S3_GW_WEB_READ_HEADER_TIMEOUT=30s +# WriteTimeout is the maximum duration before timing out +# writes of the response. It is reset whenever a new +# request's header is read. Like ReadTimeout, it does not +# let Handlers make decisions on a per-request basis. +# A zero or negative value means there will be no timeout. +S3_GW_WEB_WRITE_TIMEOUT=0 +# IdleTimeout is the maximum amount of time to wait for the +# next request when keep-alives are enabled. If IdleTimeout +# is zero, the value of ReadTimeout is used. If both are +# zero, there is no timeout. +S3_GW_WEB_IDLE_TIMEOUT=30s diff --git a/config/config.yaml b/config/config.yaml index e6eb230..20f5e3b 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -180,3 +180,30 @@ runtime: features: md5: enabled: false + +web: + # ReadTimeout is the maximum duration for reading the entire + # request, including the body. A zero or negative value means + # there will be no timeout. + read_timeout: 0 + + # ReadHeaderTimeout is the amount of time allowed to read + # request headers. The connection's read deadline is reset + # after reading the headers and the Handler can decide what + # is considered too slow for the body. If ReadHeaderTimeout + # is zero, the value of ReadTimeout is used. If both are + # zero, there is no timeout. + read_header_timeout: 30s + + # WriteTimeout is the maximum duration before timing out + # writes of the response. It is reset whenever a new + # request's header is read. Like ReadTimeout, it does not + # let Handlers make decisions on a per-request basis. + # A zero or negative value means there will be no timeout. + write_timeout: 0 + + # IdleTimeout is the maximum amount of time to wait for the + # next request when keep-alives are enabled. If IdleTimeout + # is zero, the value of ReadTimeout is used. If both are + # zero, there is no timeout. + idle_timeout: 30s diff --git a/docs/configuration.md b/docs/configuration.md index 282ae29..9f43b8b 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -187,6 +187,7 @@ There are some custom types used for brevity: | `kludge` | [Different kludge configuration](#kludge-section) | | `runtime` | [Runtime configuration](#runtime-section) | | `features` | [Features configuration](#features-section) | +| `web` | [Web server configuration](#web-section) | ### General section @@ -576,3 +577,21 @@ features: | Parameter | Type | SIGHUP reload | Default value | Description | |---------------|--------|---------------|---------------|----------------------------------------------------------------| | `md5.enabled` | `bool` | yes | false | Flag to enable return MD5 checksum in ETag headers and fields. | + +# `web` section +Contains web server configuration parameters. + +```yaml +web: + read_timeout: 0 + read_header_timeout: 30s + write_timeout: 0 + idle_timeout: 30s +``` + +| Parameter | Type | SIGHUP reload | Default value | Description | +|-----------------------|------------|---------------|---------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `read_timeout` | `duration` | no | `0` | The maximum duration for reading the entire request, including the body. A zero or negative value means there will be no timeout. | +| `read_header_timeout` | `duration` | no | `30s` | The amount of time allowed to read request headers. If `read_header_timeout` is zero, the value of `read_timeout` is used. If both are zero, there is no timeout. | +| `write_timeout` | `duration` | no | `0` | The maximum duration before timing out writes of the response. A zero or negative value means there will be no timeout. | +| `idle_timeout` | `duration` | no | `30s` | The maximum amount of time to wait for the next request when keep-alives are enabled. If `idle_timeout` is zero, the value of `read_timeout` is used. If both are zero, there is no timeout. |