This is an automated email from the ASF dual-hosted git repository.
masaori335 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new fb102991e7 Fix connect attempt retries (#13102)
fb102991e7 is described below
commit fb102991e75c89ec846d7c2f37667b4ba7f39650
Author: Masaori Koshiba <[email protected]>
AuthorDate: Wed Jun 17 06:52:12 2026 +0900
Fix connect attempt retries (#13102)
* Fix connect attempt retries
* Fix table format
---
doc/admin-guide/files/records.yaml.en.rst | 21 +-
.../api/functions/TSHttpOverridableConfig.en.rst | 269 +++++++++++----------
.../api/types/TSOverridableConfigKey.en.rst | 1 +
doc/release-notes/upgrading.en.rst | 5 +
include/cripts/Configs.hpp | 2 +
include/iocore/hostdb/HostDBProcessor.h | 2 +-
include/proxy/http/HttpConfig.h | 10 +-
include/proxy/http/HttpTransact.h | 5 +-
include/proxy/http/OverridableConfigDefs.h | 3 +-
include/ts/apidefs.h.in | 1 +
src/iocore/hostdb/HostDB.cc | 14 +-
src/proxy/http/HttpConfig.cc | 40 ++-
src/proxy/http/HttpSM.cc | 68 +++---
src/proxy/http/HttpTransact.cc | 188 ++++++++------
src/records/RecordsConfig.cc | 8 +-
.../autest-site/verifier_client.test.ext | 15 +-
.../replay/connect_down_policy_4.replay.yaml | 2 +-
tests/gold_tests/dns/connect_attempts.test.py | 5 +
tests/gold_tests/dns/dns_host_down.test.py | 14 ++
.../connect_attempts_rr_max_retries_error_log.gold | 4 +-
.../connect_attempts_rr_retries_error_log.gold | 7 +-
...nect_attempts_single_max_retries_error_log.gold | 9 +
.../connect_attempts_rr_max_retries.replay.yaml | 2 +-
.../connect_attempts_rr_no_retry.replay.yaml | 2 +-
.../replay/connect_attempts_rr_retries.replay.yaml | 59 ++---
...onnect_attempts_single_max_retries.replay.yaml} | 79 ++----
26 files changed, 461 insertions(+), 374 deletions(-)
diff --git a/doc/admin-guide/files/records.yaml.en.rst
b/doc/admin-guide/files/records.yaml.en.rst
index b362089c89..169c8b6a4c 100644
--- a/doc/admin-guide/files/records.yaml.en.rst
+++ b/doc/admin-guide/files/records.yaml.en.rst
@@ -1818,15 +1818,28 @@ Origin Server Connect Attempts
The maximum number of connection retries |TS| can make when the origin
server is not responding.
Each retry attempt lasts for `proxy.config.http.connect_attempts_timeout`_
seconds. Once the maximum number of retries is
reached, the origin is marked down (as controlled by
`proxy.config.http.connect.down.policy`_. After this, the setting
- `proxy.config.http.connect_attempts_max_retries_down_server`_ is used to
limit the number of retry attempts to the known down origin.
+ `proxy.config.http.connect_attempts_max_retries_suspect_server`_ is used to
limit the number of retry attempts when the origin is
+ in the SUSPECT state (recovering after
`proxy.config.http.down_server.cache_time`_ has elapsed).
+
+.. ts:cv:: CONFIG
proxy.config.http.connect_attempts_max_retries_suspect_server INT 1
+ :reloadable:
+ :overridable:
+
+ Maximum number of connection retries |TS| can make while an origin is in
the SUSPECT state (the first request after
+ `proxy.config.http.down_server.cache_time`_ has elapsed on a
previously-down origin). The total attempt budget for a SUSPECT
+ origin is therefore ``connect_attempts_max_retries_suspect_server + 1``
(the initial probe plus each retry). If any attempt
+ succeeds, the origin transitions back to UP; if all attempts fail, the
origin returns to DOWN for another
+ `proxy.config.http.down_server.cache_time`_ seconds. Typically smaller than
`proxy.config.http.connect_attempts_max_retries`_
+ so the recovering origin is not flooded.
.. ts:cv:: CONFIG proxy.config.http.connect_attempts_max_retries_down_server
INT 1
:reloadable:
:overridable:
+ :deprecated:
- Maximum number of connection attempts |TS| can make while an origin is
marked down per request. Typically this value is smaller than
- `proxy.config.http.connect_attempts_max_retries`_ so an error is returned
to the client faster and also to reduce the load on the down origin.
- The timeout interval `proxy.config.http.connect_attempts_timeout`_ in
seconds is used with this setting.
+ This setting is deprecated in favor of
:ts:cv:`proxy.config.http.connect_attempts_max_retries_suspect_server`. If the
+ deprecated setting is set explicitly and the replacement is not, the
deprecated value is mirrored forward and a warning is
+ logged. If both are set explicitly, the new setting wins and the deprecated
value is ignored.
.. ts:cv:: CONFIG proxy.config.http.connect_attempts_retry_backoff_base INT 0
:reloadable:
diff --git a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
index 623b40f3a1..43d98b40ad 100644
--- a/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
+++ b/doc/developer-guide/api/functions/TSHttpOverridableConfig.en.rst
@@ -65,140 +65,141 @@ Testing
:enumerator:`TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE`.
The following configurations (from ``records.yaml``) are overridable:
-======================================================================
====================================================================
-TSOverridableConfigKey Value
Configuration Value
-======================================================================
====================================================================
-:enumerator:`TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE`
:ts:cv:`proxy.config.body_factory.template_base`
-:enumerator:`TS_CONFIG_HTTP_ALLOW_HALF_OPEN`
:ts:cv:`proxy.config.http.allow_half_open`
-:enumerator:`TS_CONFIG_HTTP_ALLOW_MULTI_RANGE`
:ts:cv:`proxy.config.http.allow_multi_range`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_INSERT_CLIENT_IP`
:ts:cv:`proxy.config.http.insert_client_ip`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_CLIENT_IP`
:ts:cv:`proxy.config.http.anonymize_remove_client_ip`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_COOKIE`
:ts:cv:`proxy.config.http.anonymize_remove_cookie`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_FROM`
:ts:cv:`proxy.config.http.anonymize_remove_from`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_REFERER`
:ts:cv:`proxy.config.http.anonymize_remove_referer`
-:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_USER_AGENT`
:ts:cv:`proxy.config.http.anonymize_remove_user_agent`
-:enumerator:`TS_CONFIG_HTTP_ATTACH_SERVER_SESSION_TO_CLIENT`
:ts:cv:`proxy.config.http.attach_server_session_to_client`
-:enumerator:`TS_CONFIG_HTTP_MAX_PROXY_CYCLES`
:ts:cv:`proxy.config.http.max_proxy_cycles`
-:enumerator:`TS_CONFIG_HTTP_AUTH_SERVER_SESSION_PRIVATE`
:ts:cv:`proxy.config.http.auth_server_session_private`
-:enumerator:`TS_CONFIG_HTTP_BACKGROUND_FILL_ACTIVE_TIMEOUT`
:ts:cv:`proxy.config.http.background_fill_active_timeout`
-:enumerator:`TS_CONFIG_HTTP_BACKGROUND_FILL_COMPLETED_THRESHOLD`
:ts:cv:`proxy.config.http.background_fill_completed_threshold`
-:enumerator:`TS_CONFIG_HTTP_CACHE_CACHE_RESPONSES_TO_COOKIES`
:ts:cv:`proxy.config.http.cache.cache_responses_to_cookies`
-:enumerator:`TS_CONFIG_HTTP_CACHE_CACHE_URLS_THAT_LOOK_DYNAMIC`
:ts:cv:`proxy.config.http.cache.cache_urls_that_look_dynamic`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_QUERY`
:ts:cv:`proxy.config.http.cache.ignore_query`
-:enumerator:`TS_CONFIG_HTTP_CACHE_GENERATION`
:ts:cv:`proxy.config.http.cache.generation`
-:enumerator:`TS_CONFIG_HTTP_CACHE_GUARANTEED_MAX_LIFETIME`
:ts:cv:`proxy.config.http.cache.guaranteed_max_lifetime`
-:enumerator:`TS_CONFIG_HTTP_CACHE_GUARANTEED_MIN_LIFETIME`
:ts:cv:`proxy.config.http.cache.guaranteed_min_lifetime`
-:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_LM_FACTOR`
:ts:cv:`proxy.config.http.cache.heuristic_lm_factor`
-:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_MAX_LIFETIME`
:ts:cv:`proxy.config.http.cache.heuristic_max_lifetime`
-:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_MIN_LIFETIME`
:ts:cv:`proxy.config.http.cache.heuristic_min_lifetime`
-:enumerator:`TS_CONFIG_HTTP_CACHE_HTTP`
:ts:cv:`proxy.config.http.cache.http`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_CHARSET_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_charset_mismatch`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_ENCODING_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_encoding_mismatch`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_LANGUAGE_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_language_mismatch`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_mismatch`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION`
:ts:cv:`proxy.config.http.cache.ignore_authentication`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_CC_MAX_AGE`
:ts:cv:`proxy.config.http.cache.ignore_client_cc_max_age`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ignore_client_no_cache`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_SERVER_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ignore_server_no_cache`
-:enumerator:`TS_CONFIG_HTTP_CACHE_IMS_ON_CLIENT_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ims_on_client_no_cache`
-:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES`
:ts:cv:`proxy.config.http.cache.max_open_read_retries`
-:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_OPEN_WRITE_RETRIES`
:ts:cv:`proxy.config.http.cache.max_open_write_retries`
-:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_STALE_AGE`
:ts:cv:`proxy.config.http.cache.max_stale_age`
-:enumerator:`TS_CONFIG_HTTP_CACHE_OPEN_READ_RETRY_TIME`
:ts:cv:`proxy.config.http.cache.open_read_retry_time`
-:enumerator:`TS_CONFIG_HTTP_CACHE_OPEN_WRITE_FAIL_ACTION`
:ts:cv:`proxy.config.http.cache.open_write_fail_action`
-:enumerator:`TS_CONFIG_HTTP_CACHE_RANGE_LOOKUP`
:ts:cv:`proxy.config.http.cache.range.lookup`
-:enumerator:`TS_CONFIG_HTTP_CACHE_RANGE_WRITE`
:ts:cv:`proxy.config.http.cache.range.write`
-:enumerator:`TS_CONFIG_HTTP_CACHE_REQUIRED_HEADERS`
:ts:cv:`proxy.config.http.cache.required_headers`
-:enumerator:`TS_CONFIG_HTTP_CACHE_WHEN_TO_REVALIDATE`
:ts:cv:`proxy.config.http.cache.when_to_revalidate`
-:enumerator:`TS_CONFIG_HTTP_CHUNKING_ENABLED`
:ts:cv:`proxy.config.http.chunking_enabled`
-:enumerator:`TS_CONFIG_HTTP_CHUNKING_SIZE`
:ts:cv:`proxy.config.http.chunking.size`
-:enumerator:`TS_CONFIG_HTTP_STRICT_CHUNK_PARSING`
:ts:cv:`proxy.config.http.strict_chunk_parsing`
-:enumerator:`TS_CONFIG_HTTP_DROP_CHUNKED_TRAILERS`
:ts:cv:`proxy.config.http.drop_chunked_trailers`
-:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER`
:ts:cv:`proxy.config.http.connect_attempts_max_retries_down_server`
-:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES`
:ts:cv:`proxy.config.http.connect_attempts_max_retries`
-:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES`
:ts:cv:`proxy.config.http.connect_attempts_rr_retries`
-:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT`
:ts:cv:`proxy.config.http.connect_attempts_timeout`
-:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RETRY_BACKOFF_BASE`
:ts:cv:`proxy.config.http.connect_attempts_retry_backoff_base`
-:enumerator:`TS_CONFIG_HTTP_DEFAULT_BUFFER_SIZE`
:ts:cv:`proxy.config.http.default_buffer_size`
-:enumerator:`TS_CONFIG_HTTP_DEFAULT_BUFFER_WATER_MARK`
:ts:cv:`proxy.config.http.default_buffer_water_mark`
-:enumerator:`TS_CONFIG_HTTP_DOC_IN_CACHE_SKIP_DNS`
:ts:cv:`proxy.config.http.doc_in_cache_skip_dns`
-:enumerator:`TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME`
:ts:cv:`proxy.config.http.down_server.cache_time`
-:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_ENABLED`
:ts:cv:`proxy.config.http.flow_control.enabled`
-:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_HIGH_WATER_MARK`
:ts:cv:`proxy.config.http.flow_control.high_water`
-:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_LOW_WATER_MARK`
:ts:cv:`proxy.config.http.flow_control.low_water`
-:enumerator:`TS_CONFIG_HTTP_FORWARD_CONNECT_METHOD`
:ts:cv:`proxy.config.http.forward_connect_method`
-:enumerator:`TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT`
:ts:cv:`proxy.config.http.forward.proxy_auth_to_parent`
-:enumerator:`TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER`
:ts:cv:`proxy.config.http.global_user_agent_header`
-:enumerator:`TS_CONFIG_HTTP_INSERT_AGE_IN_RESPONSE`
:ts:cv:`proxy.config.http.insert_age_in_response`
-:enumerator:`TS_CONFIG_HTTP_INSERT_FORWARDED`
:ts:cv:`proxy.config.http.insert_forwarded`
-:enumerator:`TS_CONFIG_HTTP_INSERT_REQUEST_VIA_STR`
:ts:cv:`proxy.config.http.insert_request_via_str`
-:enumerator:`TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR`
:ts:cv:`proxy.config.http.insert_response_via_str`
-:enumerator:`TS_CONFIG_HTTP_INSERT_SQUID_X_FORWARDED_FOR`
:ts:cv:`proxy.config.http.insert_squid_x_forwarded_for`
-:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN`
:ts:cv:`proxy.config.http.keep_alive_enabled_in`
-:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT`
:ts:cv:`proxy.config.http.keep_alive_enabled_out`
-:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_IN`
:ts:cv:`proxy.config.http.keep_alive_no_activity_timeout_in`
-:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.keep_alive_no_activity_timeout_out`
-:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT`
:ts:cv:`proxy.config.http.keep_alive_post_out`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_ENABLED`
:ts:cv:`proxy.config.http.negative_caching_enabled`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_LIFETIME`
:ts:cv:`proxy.config.http.negative_caching_lifetime`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_LIST`
:ts:cv:`proxy.config.http.negative_caching_list`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_ENABLED`
:ts:cv:`proxy.config.http.negative_revalidating_enabled`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIFETIME`
:ts:cv:`proxy.config.http.negative_revalidating_lifetime`
-:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIST`
:ts:cv:`proxy.config.http.negative_revalidating_list`
-:enumerator:`TS_CONFIG_HTTP_NO_DNS_JUST_FORWARD_TO_PARENT`
:ts:cv:`proxy.config.http.no_dns_just_forward_to_parent`
-:enumerator:`TS_CONFIG_HTTP_NORMALIZE_AE`
:ts:cv:`proxy.config.http.normalize_ae`
-:enumerator:`TS_CONFIG_HTTP_NUMBER_OF_REDIRECTIONS`
:ts:cv:`proxy.config.http.number_of_redirections`
-:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_FAIL_THRESHOLD`
:ts:cv:`proxy.config.http.parent_proxy.fail_threshold`
-:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME`
:ts:cv:`proxy.config.http.parent_proxy.retry_time`
-:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS`
:ts:cv:`proxy.config.http.parent_proxy.total_connect_attempts`
-:enumerator:`TS_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS`
:ts:cv:`proxy.config.http.parent_proxy.per_parent_connect_attempts`
-:enumerator:`TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MATCH`
:ts:cv:`proxy.config.http.per_server.connection.match`
-:enumerator:`TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MAX`
:ts:cv:`proxy.config.http.per_server.connection.max`
-:enumerator:`TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED`
:ts:cv:`proxy.config.http.post.check.content_length.enabled`
-:enumerator:`TS_CONFIG_HTTP_REDIRECT_USE_ORIG_CACHE_KEY`
:ts:cv:`proxy.config.http.redirect_use_orig_cache_key`
-:enumerator:`TS_CONFIG_HTTP_REQUEST_BUFFER_ENABLED`
:ts:cv:`proxy.config.http.request_buffer_enabled`
-:enumerator:`TS_CONFIG_HTTP_REQUEST_HEADER_MAX_SIZE`
:ts:cv:`proxy.config.http.request_header_max_size`
-:enumerator:`TS_CONFIG_HTTP_RESPONSE_HEADER_MAX_SIZE`
:ts:cv:`proxy.config.http.response_header_max_size`
-:enumerator:`TS_CONFIG_HTTP_RESPONSE_SERVER_ENABLED`
:ts:cv:`proxy.config.http.response_server_enabled`
-:enumerator:`TS_CONFIG_HTTP_RESPONSE_SERVER_STR`
:ts:cv:`proxy.config.http.response_server_str`
-:enumerator:`TS_CONFIG_HTTP_SEND_HTTP11_REQUESTS`
:ts:cv:`proxy.config.http.send_http11_requests`
-:enumerator:`TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH`
:ts:cv:`proxy.config.http.server_session_sharing.match`
-:enumerator:`TS_CONFIG_HTTP_SLOW_LOG_THRESHOLD`
:ts:cv:`proxy.config.http.slow.log.threshold`
-:enumerator:`TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN`
:ts:cv:`proxy.config.http.transaction_active_timeout_in`
-:enumerator:`TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.transaction_active_timeout_out`
-:enumerator:`TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_IN`
:ts:cv:`proxy.config.http.transaction_no_activity_timeout_in`
-:enumerator:`TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.transaction_no_activity_timeout_out`
-:enumerator:`TS_CONFIG_HTTP_UNCACHEABLE_REQUESTS_BYPASS_PARENT`
:ts:cv:`proxy.config.http.uncacheable_requests_bypass_parent`
-:enumerator:`TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT`
:ts:cv:`proxy.config.net.sock_option_flag_out`
-:enumerator:`TS_CONFIG_NET_SOCK_PACKET_MARK_OUT`
:ts:cv:`proxy.config.net.sock_packet_mark_out`
-:enumerator:`TS_CONFIG_NET_SOCK_PACKET_TOS_OUT`
:ts:cv:`proxy.config.net.sock_packet_tos_out`
-:enumerator:`TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT`
:ts:cv:`proxy.config.net.sock_recv_buffer_size_out`
-:enumerator:`TS_CONFIG_NET_DEFAULT_INACTIVITY_TIMEOUT`
:ts:cv:`proxy.config.net.default_inactivity_timeout`
-:enumerator:`TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT`
:ts:cv:`proxy.config.net.sock_send_buffer_size_out`
-:enumerator:`TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB`
:ts:cv:`proxy.config.http.parent_proxy.mark_down_hostdb`
-:enumerator:`TS_CONFIG_SRV_ENABLED`
:ts:cv:`proxy.config.srv_enabled`
-:enumerator:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.cert.filename`
-:enumerator:`TS_CONFIG_SSL_CERT_FILEPATH`
:ts:cv:`proxy.config.ssl.client.cert.path`
-:enumerator:`TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_PROPERTIES`
:ts:cv:`proxy.config.ssl.client.verify.server.properties`
-:enumerator:`TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_POLICY`
:ts:cv:`proxy.config.ssl.client.verify.server.policy`
-:enumerator:`TS_CONFIG_SSL_CLIENT_SNI_POLICY`
:ts:cv:`proxy.config.ssl.client.sni_policy`
-:enumerator:`TS_CONFIG_SSL_HSTS_INCLUDE_SUBDOMAINS`
:ts:cv:`proxy.config.ssl.hsts_include_subdomains`
-:enumerator:`TS_CONFIG_SSL_HSTS_MAX_AGE`
:ts:cv:`proxy.config.ssl.hsts_max_age`
-:enumerator:`TS_CONFIG_URL_REMAP_PRISTINE_HOST_HDR`
:ts:cv:`proxy.config.url_remap.pristine_host_hdr`
-:enumerator:`TS_CONFIG_WEBSOCKET_ACTIVE_TIMEOUT`
:ts:cv:`proxy.config.websocket.active_timeout`
-:enumerator:`TS_CONFIG_WEBSOCKET_NO_ACTIVITY_TIMEOUT`
:ts:cv:`proxy.config.websocket.no_activity_timeout`
-:enumerator:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.cert.filename`
-:enumerator:`TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME`
:ts:cv:`proxy.config.ssl.client.private_key.filename`
-:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.CA.cert.filename`
-:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_PATH`
:ts:cv:`proxy.config.ssl.client.CA.cert.path`
-:enumerator:`TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE`
:ts:cv:`proxy.config.hostdb.ip_resolve`
-:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_INDEX`
:ts:cv:`proxy.config.plugin.vc.default_buffer_index`
-:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_WATER_MARK`
:ts:cv:`proxy.config.plugin.vc.default_buffer_water_mark`
-:enumerator:`TS_CONFIG_NET_SOCK_NOTSENT_LOWAT`
:ts:cv:`proxy.config.net.sock_notsent_lowat`
-:enumerator:`TS_CONFIG_BODY_FACTORY_RESPONSE_SUPPRESSION_MODE`
:ts:cv:`proxy.config.body_factory.response_suppression_mode`
-:enumerator:`TS_CONFIG_HTTP_CACHE_POST_METHOD`
:ts:cv:`proxy.config.http.cache.post_method`
-:enumerator:`TS_CONFIG_HTTP_CACHE_TARGETED_CACHE_CONTROL_HEADERS`
:ts:cv:`proxy.config.http.cache.targeted_cache_control_headers`
-======================================================================
====================================================================
+========================================================================
====================================================================
+TSOverridableConfigKey Value
Configuration Value
+========================================================================
====================================================================
+:enumerator:`TS_CONFIG_BODY_FACTORY_TEMPLATE_BASE`
:ts:cv:`proxy.config.body_factory.template_base`
+:enumerator:`TS_CONFIG_HTTP_ALLOW_HALF_OPEN`
:ts:cv:`proxy.config.http.allow_half_open`
+:enumerator:`TS_CONFIG_HTTP_ALLOW_MULTI_RANGE`
:ts:cv:`proxy.config.http.allow_multi_range`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_INSERT_CLIENT_IP`
:ts:cv:`proxy.config.http.insert_client_ip`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_CLIENT_IP`
:ts:cv:`proxy.config.http.anonymize_remove_client_ip`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_COOKIE`
:ts:cv:`proxy.config.http.anonymize_remove_cookie`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_FROM`
:ts:cv:`proxy.config.http.anonymize_remove_from`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_REFERER`
:ts:cv:`proxy.config.http.anonymize_remove_referer`
+:enumerator:`TS_CONFIG_HTTP_ANONYMIZE_REMOVE_USER_AGENT`
:ts:cv:`proxy.config.http.anonymize_remove_user_agent`
+:enumerator:`TS_CONFIG_HTTP_ATTACH_SERVER_SESSION_TO_CLIENT`
:ts:cv:`proxy.config.http.attach_server_session_to_client`
+:enumerator:`TS_CONFIG_HTTP_MAX_PROXY_CYCLES`
:ts:cv:`proxy.config.http.max_proxy_cycles`
+:enumerator:`TS_CONFIG_HTTP_AUTH_SERVER_SESSION_PRIVATE`
:ts:cv:`proxy.config.http.auth_server_session_private`
+:enumerator:`TS_CONFIG_HTTP_BACKGROUND_FILL_ACTIVE_TIMEOUT`
:ts:cv:`proxy.config.http.background_fill_active_timeout`
+:enumerator:`TS_CONFIG_HTTP_BACKGROUND_FILL_COMPLETED_THRESHOLD`
:ts:cv:`proxy.config.http.background_fill_completed_threshold`
+:enumerator:`TS_CONFIG_HTTP_CACHE_CACHE_RESPONSES_TO_COOKIES`
:ts:cv:`proxy.config.http.cache.cache_responses_to_cookies`
+:enumerator:`TS_CONFIG_HTTP_CACHE_CACHE_URLS_THAT_LOOK_DYNAMIC`
:ts:cv:`proxy.config.http.cache.cache_urls_that_look_dynamic`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_QUERY`
:ts:cv:`proxy.config.http.cache.ignore_query`
+:enumerator:`TS_CONFIG_HTTP_CACHE_GENERATION`
:ts:cv:`proxy.config.http.cache.generation`
+:enumerator:`TS_CONFIG_HTTP_CACHE_GUARANTEED_MAX_LIFETIME`
:ts:cv:`proxy.config.http.cache.guaranteed_max_lifetime`
+:enumerator:`TS_CONFIG_HTTP_CACHE_GUARANTEED_MIN_LIFETIME`
:ts:cv:`proxy.config.http.cache.guaranteed_min_lifetime`
+:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_LM_FACTOR`
:ts:cv:`proxy.config.http.cache.heuristic_lm_factor`
+:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_MAX_LIFETIME`
:ts:cv:`proxy.config.http.cache.heuristic_max_lifetime`
+:enumerator:`TS_CONFIG_HTTP_CACHE_HEURISTIC_MIN_LIFETIME`
:ts:cv:`proxy.config.http.cache.heuristic_min_lifetime`
+:enumerator:`TS_CONFIG_HTTP_CACHE_HTTP`
:ts:cv:`proxy.config.http.cache.http`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_CHARSET_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_charset_mismatch`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_ENCODING_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_encoding_mismatch`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_LANGUAGE_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_language_mismatch`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_ACCEPT_MISMATCH`
:ts:cv:`proxy.config.http.cache.ignore_accept_mismatch`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_AUTHENTICATION`
:ts:cv:`proxy.config.http.cache.ignore_authentication`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_CC_MAX_AGE`
:ts:cv:`proxy.config.http.cache.ignore_client_cc_max_age`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_CLIENT_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ignore_client_no_cache`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IGNORE_SERVER_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ignore_server_no_cache`
+:enumerator:`TS_CONFIG_HTTP_CACHE_IMS_ON_CLIENT_NO_CACHE`
:ts:cv:`proxy.config.http.cache.ims_on_client_no_cache`
+:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_OPEN_READ_RETRIES`
:ts:cv:`proxy.config.http.cache.max_open_read_retries`
+:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_OPEN_WRITE_RETRIES`
:ts:cv:`proxy.config.http.cache.max_open_write_retries`
+:enumerator:`TS_CONFIG_HTTP_CACHE_MAX_STALE_AGE`
:ts:cv:`proxy.config.http.cache.max_stale_age`
+:enumerator:`TS_CONFIG_HTTP_CACHE_OPEN_READ_RETRY_TIME`
:ts:cv:`proxy.config.http.cache.open_read_retry_time`
+:enumerator:`TS_CONFIG_HTTP_CACHE_OPEN_WRITE_FAIL_ACTION`
:ts:cv:`proxy.config.http.cache.open_write_fail_action`
+:enumerator:`TS_CONFIG_HTTP_CACHE_RANGE_LOOKUP`
:ts:cv:`proxy.config.http.cache.range.lookup`
+:enumerator:`TS_CONFIG_HTTP_CACHE_RANGE_WRITE`
:ts:cv:`proxy.config.http.cache.range.write`
+:enumerator:`TS_CONFIG_HTTP_CACHE_REQUIRED_HEADERS`
:ts:cv:`proxy.config.http.cache.required_headers`
+:enumerator:`TS_CONFIG_HTTP_CACHE_WHEN_TO_REVALIDATE`
:ts:cv:`proxy.config.http.cache.when_to_revalidate`
+:enumerator:`TS_CONFIG_HTTP_CHUNKING_ENABLED`
:ts:cv:`proxy.config.http.chunking_enabled`
+:enumerator:`TS_CONFIG_HTTP_CHUNKING_SIZE`
:ts:cv:`proxy.config.http.chunking.size`
+:enumerator:`TS_CONFIG_HTTP_STRICT_CHUNK_PARSING`
:ts:cv:`proxy.config.http.strict_chunk_parsing`
+:enumerator:`TS_CONFIG_HTTP_DROP_CHUNKED_TRAILERS`
:ts:cv:`proxy.config.http.drop_chunked_trailers`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER`
:ts:cv:`proxy.config.http.connect_attempts_max_retries_down_server`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_SUSPECT_SERVER`
:ts:cv:`proxy.config.http.connect_attempts_max_retries_suspect_server`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES`
:ts:cv:`proxy.config.http.connect_attempts_max_retries`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES`
:ts:cv:`proxy.config.http.connect_attempts_rr_retries`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT`
:ts:cv:`proxy.config.http.connect_attempts_timeout`
+:enumerator:`TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RETRY_BACKOFF_BASE`
:ts:cv:`proxy.config.http.connect_attempts_retry_backoff_base`
+:enumerator:`TS_CONFIG_HTTP_DEFAULT_BUFFER_SIZE`
:ts:cv:`proxy.config.http.default_buffer_size`
+:enumerator:`TS_CONFIG_HTTP_DEFAULT_BUFFER_WATER_MARK`
:ts:cv:`proxy.config.http.default_buffer_water_mark`
+:enumerator:`TS_CONFIG_HTTP_DOC_IN_CACHE_SKIP_DNS`
:ts:cv:`proxy.config.http.doc_in_cache_skip_dns`
+:enumerator:`TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME`
:ts:cv:`proxy.config.http.down_server.cache_time`
+:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_ENABLED`
:ts:cv:`proxy.config.http.flow_control.enabled`
+:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_HIGH_WATER_MARK`
:ts:cv:`proxy.config.http.flow_control.high_water`
+:enumerator:`TS_CONFIG_HTTP_FLOW_CONTROL_LOW_WATER_MARK`
:ts:cv:`proxy.config.http.flow_control.low_water`
+:enumerator:`TS_CONFIG_HTTP_FORWARD_CONNECT_METHOD`
:ts:cv:`proxy.config.http.forward_connect_method`
+:enumerator:`TS_CONFIG_HTTP_FORWARD_PROXY_AUTH_TO_PARENT`
:ts:cv:`proxy.config.http.forward.proxy_auth_to_parent`
+:enumerator:`TS_CONFIG_HTTP_GLOBAL_USER_AGENT_HEADER`
:ts:cv:`proxy.config.http.global_user_agent_header`
+:enumerator:`TS_CONFIG_HTTP_INSERT_AGE_IN_RESPONSE`
:ts:cv:`proxy.config.http.insert_age_in_response`
+:enumerator:`TS_CONFIG_HTTP_INSERT_FORWARDED`
:ts:cv:`proxy.config.http.insert_forwarded`
+:enumerator:`TS_CONFIG_HTTP_INSERT_REQUEST_VIA_STR`
:ts:cv:`proxy.config.http.insert_request_via_str`
+:enumerator:`TS_CONFIG_HTTP_INSERT_RESPONSE_VIA_STR`
:ts:cv:`proxy.config.http.insert_response_via_str`
+:enumerator:`TS_CONFIG_HTTP_INSERT_SQUID_X_FORWARDED_FOR`
:ts:cv:`proxy.config.http.insert_squid_x_forwarded_for`
+:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_IN`
:ts:cv:`proxy.config.http.keep_alive_enabled_in`
+:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_ENABLED_OUT`
:ts:cv:`proxy.config.http.keep_alive_enabled_out`
+:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_IN`
:ts:cv:`proxy.config.http.keep_alive_no_activity_timeout_in`
+:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_NO_ACTIVITY_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.keep_alive_no_activity_timeout_out`
+:enumerator:`TS_CONFIG_HTTP_KEEP_ALIVE_POST_OUT`
:ts:cv:`proxy.config.http.keep_alive_post_out`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_ENABLED`
:ts:cv:`proxy.config.http.negative_caching_enabled`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_LIFETIME`
:ts:cv:`proxy.config.http.negative_caching_lifetime`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_CACHING_LIST`
:ts:cv:`proxy.config.http.negative_caching_list`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_ENABLED`
:ts:cv:`proxy.config.http.negative_revalidating_enabled`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIFETIME`
:ts:cv:`proxy.config.http.negative_revalidating_lifetime`
+:enumerator:`TS_CONFIG_HTTP_NEGATIVE_REVALIDATING_LIST`
:ts:cv:`proxy.config.http.negative_revalidating_list`
+:enumerator:`TS_CONFIG_HTTP_NO_DNS_JUST_FORWARD_TO_PARENT`
:ts:cv:`proxy.config.http.no_dns_just_forward_to_parent`
+:enumerator:`TS_CONFIG_HTTP_NORMALIZE_AE`
:ts:cv:`proxy.config.http.normalize_ae`
+:enumerator:`TS_CONFIG_HTTP_NUMBER_OF_REDIRECTIONS`
:ts:cv:`proxy.config.http.number_of_redirections`
+:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_FAIL_THRESHOLD`
:ts:cv:`proxy.config.http.parent_proxy.fail_threshold`
+:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_RETRY_TIME`
:ts:cv:`proxy.config.http.parent_proxy.retry_time`
+:enumerator:`TS_CONFIG_HTTP_PARENT_PROXY_TOTAL_CONNECT_ATTEMPTS`
:ts:cv:`proxy.config.http.parent_proxy.total_connect_attempts`
+:enumerator:`TS_CONFIG_HTTP_PER_PARENT_CONNECT_ATTEMPTS`
:ts:cv:`proxy.config.http.parent_proxy.per_parent_connect_attempts`
+:enumerator:`TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MATCH`
:ts:cv:`proxy.config.http.per_server.connection.match`
+:enumerator:`TS_CONFIG_HTTP_PER_SERVER_CONNECTION_MAX`
:ts:cv:`proxy.config.http.per_server.connection.max`
+:enumerator:`TS_CONFIG_HTTP_POST_CHECK_CONTENT_LENGTH_ENABLED`
:ts:cv:`proxy.config.http.post.check.content_length.enabled`
+:enumerator:`TS_CONFIG_HTTP_REDIRECT_USE_ORIG_CACHE_KEY`
:ts:cv:`proxy.config.http.redirect_use_orig_cache_key`
+:enumerator:`TS_CONFIG_HTTP_REQUEST_BUFFER_ENABLED`
:ts:cv:`proxy.config.http.request_buffer_enabled`
+:enumerator:`TS_CONFIG_HTTP_REQUEST_HEADER_MAX_SIZE`
:ts:cv:`proxy.config.http.request_header_max_size`
+:enumerator:`TS_CONFIG_HTTP_RESPONSE_HEADER_MAX_SIZE`
:ts:cv:`proxy.config.http.response_header_max_size`
+:enumerator:`TS_CONFIG_HTTP_RESPONSE_SERVER_ENABLED`
:ts:cv:`proxy.config.http.response_server_enabled`
+:enumerator:`TS_CONFIG_HTTP_RESPONSE_SERVER_STR`
:ts:cv:`proxy.config.http.response_server_str`
+:enumerator:`TS_CONFIG_HTTP_SEND_HTTP11_REQUESTS`
:ts:cv:`proxy.config.http.send_http11_requests`
+:enumerator:`TS_CONFIG_HTTP_SERVER_SESSION_SHARING_MATCH`
:ts:cv:`proxy.config.http.server_session_sharing.match`
+:enumerator:`TS_CONFIG_HTTP_SLOW_LOG_THRESHOLD`
:ts:cv:`proxy.config.http.slow.log.threshold`
+:enumerator:`TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_IN`
:ts:cv:`proxy.config.http.transaction_active_timeout_in`
+:enumerator:`TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.transaction_active_timeout_out`
+:enumerator:`TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_IN`
:ts:cv:`proxy.config.http.transaction_no_activity_timeout_in`
+:enumerator:`TS_CONFIG_HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT`
:ts:cv:`proxy.config.http.transaction_no_activity_timeout_out`
+:enumerator:`TS_CONFIG_HTTP_UNCACHEABLE_REQUESTS_BYPASS_PARENT`
:ts:cv:`proxy.config.http.uncacheable_requests_bypass_parent`
+:enumerator:`TS_CONFIG_NET_SOCK_OPTION_FLAG_OUT`
:ts:cv:`proxy.config.net.sock_option_flag_out`
+:enumerator:`TS_CONFIG_NET_SOCK_PACKET_MARK_OUT`
:ts:cv:`proxy.config.net.sock_packet_mark_out`
+:enumerator:`TS_CONFIG_NET_SOCK_PACKET_TOS_OUT`
:ts:cv:`proxy.config.net.sock_packet_tos_out`
+:enumerator:`TS_CONFIG_NET_SOCK_RECV_BUFFER_SIZE_OUT`
:ts:cv:`proxy.config.net.sock_recv_buffer_size_out`
+:enumerator:`TS_CONFIG_NET_DEFAULT_INACTIVITY_TIMEOUT`
:ts:cv:`proxy.config.net.default_inactivity_timeout`
+:enumerator:`TS_CONFIG_NET_SOCK_SEND_BUFFER_SIZE_OUT`
:ts:cv:`proxy.config.net.sock_send_buffer_size_out`
+:enumerator:`TS_CONFIG_PARENT_FAILURES_UPDATE_HOSTDB`
:ts:cv:`proxy.config.http.parent_proxy.mark_down_hostdb`
+:enumerator:`TS_CONFIG_SRV_ENABLED`
:ts:cv:`proxy.config.srv_enabled`
+:enumerator:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.cert.filename`
+:enumerator:`TS_CONFIG_SSL_CERT_FILEPATH`
:ts:cv:`proxy.config.ssl.client.cert.path`
+:enumerator:`TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_PROPERTIES`
:ts:cv:`proxy.config.ssl.client.verify.server.properties`
+:enumerator:`TS_CONFIG_SSL_CLIENT_VERIFY_SERVER_POLICY`
:ts:cv:`proxy.config.ssl.client.verify.server.policy`
+:enumerator:`TS_CONFIG_SSL_CLIENT_SNI_POLICY`
:ts:cv:`proxy.config.ssl.client.sni_policy`
+:enumerator:`TS_CONFIG_SSL_HSTS_INCLUDE_SUBDOMAINS`
:ts:cv:`proxy.config.ssl.hsts_include_subdomains`
+:enumerator:`TS_CONFIG_SSL_HSTS_MAX_AGE`
:ts:cv:`proxy.config.ssl.hsts_max_age`
+:enumerator:`TS_CONFIG_URL_REMAP_PRISTINE_HOST_HDR`
:ts:cv:`proxy.config.url_remap.pristine_host_hdr`
+:enumerator:`TS_CONFIG_WEBSOCKET_ACTIVE_TIMEOUT`
:ts:cv:`proxy.config.websocket.active_timeout`
+:enumerator:`TS_CONFIG_WEBSOCKET_NO_ACTIVITY_TIMEOUT`
:ts:cv:`proxy.config.websocket.no_activity_timeout`
+:enumerator:`TS_CONFIG_SSL_CLIENT_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.cert.filename`
+:enumerator:`TS_CONFIG_SSL_CLIENT_PRIVATE_KEY_FILENAME`
:ts:cv:`proxy.config.ssl.client.private_key.filename`
+:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_FILENAME`
:ts:cv:`proxy.config.ssl.client.CA.cert.filename`
+:enumerator:`TS_CONFIG_SSL_CLIENT_CA_CERT_PATH`
:ts:cv:`proxy.config.ssl.client.CA.cert.path`
+:enumerator:`TS_CONFIG_HTTP_HOST_RESOLUTION_PREFERENCE`
:ts:cv:`proxy.config.hostdb.ip_resolve`
+:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_INDEX`
:ts:cv:`proxy.config.plugin.vc.default_buffer_index`
+:enumerator:`TS_CONFIG_PLUGIN_VC_DEFAULT_BUFFER_WATER_MARK`
:ts:cv:`proxy.config.plugin.vc.default_buffer_water_mark`
+:enumerator:`TS_CONFIG_NET_SOCK_NOTSENT_LOWAT`
:ts:cv:`proxy.config.net.sock_notsent_lowat`
+:enumerator:`TS_CONFIG_BODY_FACTORY_RESPONSE_SUPPRESSION_MODE`
:ts:cv:`proxy.config.body_factory.response_suppression_mode`
+:enumerator:`TS_CONFIG_HTTP_CACHE_POST_METHOD`
:ts:cv:`proxy.config.http.cache.post_method`
+:enumerator:`TS_CONFIG_HTTP_CACHE_TARGETED_CACHE_CONTROL_HEADERS`
:ts:cv:`proxy.config.http.cache.targeted_cache_control_headers`
+========================================================================
====================================================================
Examples
========
diff --git a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
index 9d200845c6..4ce7c1712d 100644
--- a/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
+++ b/doc/developer-guide/api/types/TSOverridableConfigKey.en.rst
@@ -79,6 +79,7 @@ Enumeration Members
.. enumerator:: TS_CONFIG_HTTP_ORIGIN_MAX_CONNECTIONS
.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES
.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER
+.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_SUSPECT_SERVER
.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES
.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT
.. enumerator:: TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RETRY_BACKOFF_BASE
diff --git a/doc/release-notes/upgrading.en.rst
b/doc/release-notes/upgrading.en.rst
index c55f4a18df..0548c19b72 100644
--- a/doc/release-notes/upgrading.en.rst
+++ b/doc/release-notes/upgrading.en.rst
@@ -146,6 +146,11 @@ The following :file:`records.yaml` changes have been made:
- The records.yaml entry ``proxy.config.http.down_server.abort_threshold`` has
been removed.
- The records.yaml entry
``proxy.config.http.connect_attempts_max_retries_dead_server`` has been renamed
to :ts:cv:`proxy.config.http.connect_attempts_max_retries_down_server`.
+- The records.yaml entry
``proxy.config.http.connect_attempts_max_retries_down_server`` is now
deprecated in favor of
+ :ts:cv:`proxy.config.http.connect_attempts_max_retries_suspect_server`. The
new name aligns with the
+ ``HostDBInfo::State::SUSPECT`` state it actually applies to (a recovering
origin allowed a limited probe budget after
+ :ts:cv:`proxy.config.http.down_server.cache_time` elapses). When only the
deprecated record is set, its value is mirrored
+ forward to the new record and a warning is logged. When both are set, the
new record wins.
- The entry ``proxy.config.http.connect.dead.policy`` has been renamed to
:ts:cv:`proxy.config.http.connect.down.policy`.
- The records.yaml entry
``proxy.config.http.parent_proxy.connect_attempts_timeout`` and
``proxy.config.http.post_connect_attempts_timeout`` have been removed.
Instead use
diff --git a/include/cripts/Configs.hpp b/include/cripts/Configs.hpp
index c2f4597a6a..79460327e7 100644
--- a/include/cripts/Configs.hpp
+++ b/include/cripts/Configs.hpp
@@ -154,6 +154,8 @@ private:
cripts::IntConfig
connect_attempts_max_retries{"proxy.config.http.connect_attempts_max_retries"};
cripts::IntConfig
connect_attempts_max_retries_down_server{"proxy.config.http.connect_attempts_max_retries_down_server"};
+ cripts::IntConfig connect_attempts_max_retries_suspect_server{
+ "proxy.config.http.connect_attempts_max_retries_suspect_server"};
cripts::IntConfig
connect_attempts_rr_retries{"proxy.config.http.connect_attempts_rr_retries"};
cripts::IntConfig
connect_attempts_timeout{"proxy.config.http.connect_attempts_timeout"};
cripts::IntConfig
default_buffer_size{"proxy.config.http.default_buffer_size"};
diff --git a/include/iocore/hostdb/HostDBProcessor.h
b/include/iocore/hostdb/HostDBProcessor.h
index c369aace4f..1a274a10e0 100644
--- a/include/iocore/hostdb/HostDBProcessor.h
+++ b/include/iocore/hostdb/HostDBProcessor.h
@@ -582,7 +582,7 @@ struct ResolveInfo {
bool mark_active_server_up();
/// Select / resolve to the next RR entry for the record.
- bool select_next_rr();
+ bool select_next_rr(ts_time now, ts_seconds fail_window);
bool is_srv() const;
};
diff --git a/include/proxy/http/HttpConfig.h b/include/proxy/http/HttpConfig.h
index c5989c3620..a0e7ed7d9b 100644
--- a/include/proxy/http/HttpConfig.h
+++ b/include/proxy/http/HttpConfig.h
@@ -706,11 +706,11 @@ struct OverridableHttpConfigParams {
////////////////////////////////////
// origin server connect attempts //
////////////////////////////////////
- MgmtInt connect_attempts_max_retries = 0;
- MgmtInt connect_attempts_max_retries_down_server = 3;
- MgmtInt connect_attempts_rr_retries = 3;
- MgmtInt connect_attempts_timeout = 30;
- MgmtInt connect_attempts_retry_backoff_base = 0;
+ MgmtInt connect_attempts_max_retries = 0;
+ MgmtInt connect_attempts_max_retries_suspect_server = 1;
+ MgmtInt connect_attempts_rr_retries = 3;
+ MgmtInt connect_attempts_timeout = 30;
+ MgmtInt connect_attempts_retry_backoff_base = 0;
MgmtInt connect_down_policy = 2;
diff --git a/include/proxy/http/HttpTransact.h
b/include/proxy/http/HttpTransact.h
index a6d48a12f7..9215f5508e 100644
--- a/include/proxy/http/HttpTransact.h
+++ b/include/proxy/http/HttpTransact.h
@@ -1003,7 +1003,6 @@ public:
static void Forbidden(State *s);
static void SelfLoop(State *s);
static void TooEarly(State *s);
- static void OriginDown(State *s);
static void PostActiveTimeoutResponse(State *s);
static void PostInactiveTimeoutResponse(State *s);
static void DecideCacheLookup(State *s);
@@ -1034,7 +1033,7 @@ public:
static void handle_response_from_parent_plugin(State *s);
static void handle_response_from_server(State *s);
static void delete_server_rr_entry(State *s, int max_retries);
- static void retry_server_connection_not_open(State *s, ServerState_t
conn_state, unsigned max_retries);
+ static void retry_server_connection_not_open(State *s, unsigned max_retries);
static void error_log_connection_failure(State *s, ServerState_t conn_state);
static void handle_server_connection_not_open(State *s);
static void handle_forward_server_connection_open(State *s);
@@ -1078,6 +1077,8 @@ public:
static bool handle_trace_and_options_requests(State *s, HTTPHdr
*incoming_hdr);
static void bootstrap_state_variables_from_request(State *s, HTTPHdr
*incoming_request);
+ static uint8_t origin_server_connect_attempts_max_retries(State *s);
+
// WARNING: this function may be called multiple times for the same
transaction.
//
static void initialize_state_variables_from_request(State *s, HTTPHdr
*obsolete_incoming_request);
diff --git a/include/proxy/http/OverridableConfigDefs.h
b/include/proxy/http/OverridableConfigDefs.h
index a21e57d70a..bf00fc3def 100644
--- a/include/proxy/http/OverridableConfigDefs.h
+++ b/include/proxy/http/OverridableConfigDefs.h
@@ -160,7 +160,8 @@
X(HTTP_TRANSACTION_NO_ACTIVITY_TIMEOUT_OUT,
transaction_no_activity_timeout_out,
"proxy.config.http.transaction_no_activity_timeout_out", INT,
GENERIC) \
X(HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT,
transaction_active_timeout_out,
"proxy.config.http.transaction_active_timeout_out", INT,
GENERIC) \
X(HTTP_CONNECT_ATTEMPTS_MAX_RETRIES,
connect_attempts_max_retries,
"proxy.config.http.connect_attempts_max_retries", INT,
GENERIC) \
- X(HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER,
connect_attempts_max_retries_down_server,
"proxy.config.http.connect_attempts_max_retries_down_server", INT,
GENERIC) \
+ X(HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER,
connect_attempts_max_retries_suspect_server,
"proxy.config.http.connect_attempts_max_retries_down_server", INT,
GENERIC) \
+ X(HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_SUSPECT_SERVER,
connect_attempts_max_retries_suspect_server,
"proxy.config.http.connect_attempts_max_retries_suspect_server", INT,
GENERIC) \
X(HTTP_CONNECT_ATTEMPTS_RR_RETRIES,
connect_attempts_rr_retries,
"proxy.config.http.connect_attempts_rr_retries", INT,
GENERIC) \
X(HTTP_CONNECT_ATTEMPTS_TIMEOUT, connect_attempts_timeout,
"proxy.config.http.connect_attempts_timeout",
INT, GENERIC) \
X(HTTP_DOWN_SERVER_CACHE_TIME, down_server_timeout,
"proxy.config.http.down_server.cache_time",
INT, HttpDownServerCacheTimeConv) \
diff --git a/include/ts/apidefs.h.in b/include/ts/apidefs.h.in
index bce145c8a4..145f1e83a8 100644
--- a/include/ts/apidefs.h.in
+++ b/include/ts/apidefs.h.in
@@ -825,6 +825,7 @@ enum TSOverridableConfigKey {
TS_CONFIG_HTTP_TRANSACTION_ACTIVE_TIMEOUT_OUT,
TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES,
TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_DOWN_SERVER,
+ TS_CONFIG_HTTP_CONNECT_ATTEMPTS_MAX_RETRIES_SUSPECT_SERVER,
TS_CONFIG_HTTP_CONNECT_ATTEMPTS_RR_RETRIES,
TS_CONFIG_HTTP_CONNECT_ATTEMPTS_TIMEOUT,
TS_CONFIG_HTTP_DOWN_SERVER_CACHE_TIME,
diff --git a/src/iocore/hostdb/HostDB.cc b/src/iocore/hostdb/HostDB.cc
index f225aeae1c..fc7bc40fea 100644
--- a/src/iocore/hostdb/HostDB.cc
+++ b/src/iocore/hostdb/HostDB.cc
@@ -1706,13 +1706,19 @@ ResolveInfo::set_active(HostDBInfo *info)
}
bool
-ResolveInfo::select_next_rr()
+ResolveInfo::select_next_rr(ts_time now, ts_seconds fail_window)
{
if (active) {
if (auto rr_info{this->record->rr_info()}; rr_info.count() > 1) {
- unsigned limit = active - rr_info.data(), idx = (limit + 1) %
rr_info.count();
- while ((idx = (idx + 1) % rr_info.count()) != limit &&
!rr_info[idx].is_up()) {}
- active = &rr_info[idx];
+ const unsigned limit = active - rr_info.data();
+ size_t idx = (limit + 1) % rr_info.count();
+ for (; idx != limit; idx = (idx + 1) % rr_info.count()) {
+ if (!rr_info[idx].is_down(now, fail_window)) {
+ active = &rr_info[idx];
+ break;
+ }
+ }
+
return idx != limit; // if the active record was actually changed.
}
}
diff --git a/src/proxy/http/HttpConfig.cc b/src/proxy/http/HttpConfig.cc
index aa9775eda1..2bfb487b43 100644
--- a/src/proxy/http/HttpConfig.cc
+++ b/src/proxy/http/HttpConfig.cc
@@ -1043,8 +1043,8 @@ HttpConfig::startup()
HttpEstablishStaticConfigFloat(c.oride.background_fill_threshold,
"proxy.config.http.background_fill_completed_threshold");
HttpEstablishStaticConfigLongLong(c.oride.connect_attempts_max_retries,
"proxy.config.http.connect_attempts_max_retries");
-
HttpEstablishStaticConfigLongLong(c.oride.connect_attempts_max_retries_down_server,
-
"proxy.config.http.connect_attempts_max_retries_down_server");
+
HttpEstablishStaticConfigLongLong(c.oride.connect_attempts_max_retries_suspect_server,
+
"proxy.config.http.connect_attempts_max_retries_suspect_server");
HttpEstablishStaticConfigLongLong(c.oride.connect_attempts_retry_backoff_base,
"proxy.config.http.connect_attempts_retry_backoff_base");
@@ -1340,14 +1340,46 @@ HttpConfig::reconfigure()
params->oride.background_fill_active_timeout =
m_master.oride.background_fill_active_timeout;
params->oride.background_fill_threshold =
m_master.oride.background_fill_threshold;
- params->oride.connect_attempts_max_retries =
m_master.oride.connect_attempts_max_retries;
- params->oride.connect_attempts_max_retries_down_server =
m_master.oride.connect_attempts_max_retries_down_server;
+ params->oride.connect_attempts_max_retries =
m_master.oride.connect_attempts_max_retries;
+ params->oride.connect_attempts_max_retries_suspect_server =
m_master.oride.connect_attempts_max_retries_suspect_server;
+
+ // Deprecation handling for connect_attempts_max_retries_down_server: if the
operator explicitly set the deprecated record
+ // but did not set the replacement, mirror the value forward so existing
configs keep working. If both are set, the new
+ // record wins and the deprecated one is ignored. Always warn when the
deprecated record is explicitly set. The deprecated
+ // record has no bound struct field; fetch its value on demand from RecCore.
+ {
+ RecSourceT old_src = REC_SOURCE_NULL;
+ RecSourceT new_src = REC_SOURCE_NULL;
+
RecGetRecordSource("proxy.config.http.connect_attempts_max_retries_down_server",
&old_src);
+
RecGetRecordSource("proxy.config.http.connect_attempts_max_retries_suspect_server",
&new_src);
+ const bool old_explicit = (old_src == REC_SOURCE_EXPLICIT || old_src ==
REC_SOURCE_ENV);
+ const bool new_explicit = (new_src == REC_SOURCE_EXPLICIT || new_src ==
REC_SOURCE_ENV);
+ if (old_explicit && !new_explicit) {
+ RecInt deprecated_val =
RecGetRecordInt("proxy.config.http.connect_attempts_max_retries_down_server")
+
.value_or(params->oride.connect_attempts_max_retries_suspect_server);
+ Warning("proxy.config.http.connect_attempts_max_retries_down_server is
deprecated; "
+ "use
proxy.config.http.connect_attempts_max_retries_suspect_server instead. "
+ "Using deprecated value %" PRIu64 " for now.",
+ deprecated_val);
+ params->oride.connect_attempts_max_retries_suspect_server =
deprecated_val;
+ } else if (old_explicit && new_explicit) {
+ Warning("proxy.config.http.connect_attempts_max_retries_down_server is
deprecated and is being ignored "
+ "in favor of
proxy.config.http.connect_attempts_max_retries_suspect_server (%" PRIu64 ").",
+ m_master.oride.connect_attempts_max_retries_suspect_server);
+ }
+ }
+
if (m_master.oride.connect_attempts_rr_retries >
params->oride.connect_attempts_max_retries) {
Warning("connect_attempts_rr_retries (%" PRIu64 ") is greater than "
"connect_attempts_max_retries (%" PRIu64 "), this means requests "
"will never redispatch to another server",
m_master.oride.connect_attempts_rr_retries,
params->oride.connect_attempts_max_retries);
}
+ if (m_master.oride.connect_attempts_rr_retries > 0 &&
params->oride.connect_attempts_max_retries_suspect_server == 0) {
+ Warning("connect_attempts_max_retries_suspect_server=0 with round-robin
enabled leaves no retry budget for recovering "
+ "(SUSPECT) origins beyond the initial attempt; "
+ "setting
proxy.config.http.connect_attempts_max_retries_suspect_server >= 1 is
recommended");
+ }
params->oride.connect_attempts_retry_backoff_base =
m_master.oride.connect_attempts_retry_backoff_base;
params->oride.connect_attempts_rr_retries =
m_master.oride.connect_attempts_rr_retries;
diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc
index 09c3a46c0e..0439ee683e 100644
--- a/src/proxy/http/HttpSM.cc
+++ b/src/proxy/http/HttpSM.cc
@@ -24,6 +24,7 @@
#include "proxy/http/HttpConfig.h"
#include "tscore/ink_hrtime.h"
+#include "tscore/ink_time.h"
#include "tsutil/Metrics.h"
#include "tsutil/StringCompare.h"
#include "tsutil/ts_bw_format.h"
@@ -4771,9 +4772,12 @@ HttpSM::do_hostdb_update_if_necessary()
t_state.dns_info.active->http_version = t_state.updated_server_version;
}
+ char addrbuf[INET6_ADDRPORTSTRLEN];
+ SMDbg(dbg_ctl_http, "update hostdb info: %s",
ats_ip_nptop(&t_state.current.server->dst_addr.sa, addrbuf, sizeof(addrbuf)));
+
// Check to see if we need to report or clear a connection failure
if (track_connect_fail()) {
- this->mark_host_failure(&t_state.dns_info,
ts_clock::from_time_t(t_state.client_request_time));
+ this->mark_host_failure(&t_state.dns_info, ts_clock::now());
} else {
if (t_state.dns_info.mark_active_server_up()) {
char addrbuf[INET6_ADDRPORTSTRLEN];
@@ -4788,8 +4792,6 @@ HttpSM::do_hostdb_update_if_necessary()
}
}
- char addrbuf[INET6_ADDRPORTSTRLEN];
- SMDbg(dbg_ctl_http, "server info = %s",
ats_ip_nptop(&t_state.current.server->dst_addr.sa, addrbuf, sizeof(addrbuf)));
return;
}
@@ -5597,12 +5599,6 @@ HttpSM::do_http_server_open(bool raw, bool only_direct)
return;
}
}
- if (HttpTransact::is_server_negative_cached(&t_state) == true &&
- t_state.txn_conf->connect_attempts_max_retries_down_server <= 0) {
- SMDbg(dbg_ctl_http_seq, "Not connecting to the server because it is marked
down.");
- call_transact_and_set_next_state(HttpTransact::OriginDown);
- return;
- }
// Check for self loop.
if (!_ua.get_txn()->is_outbound_transparent() &&
HttpTransact::will_this_request_self_loop(&t_state)) {
@@ -6053,34 +6049,36 @@ HttpSM::do_transform_open()
void
HttpSM::mark_host_failure(ResolveInfo *info, ts_time time_down)
{
- char addrbuf[INET6_ADDRPORTSTRLEN];
+ ink_assert(time_down != TS_TIME_ZERO);
- if (info->active) {
- if (time_down != TS_TIME_ZERO) {
- ats_ip_nptop(&t_state.current.server->dst_addr.sa, addrbuf,
sizeof(addrbuf));
- // Increment the fail_count
- if (auto [down, fail_count] =
info->active->increment_fail_count(time_down,
t_state.txn_conf->connect_attempts_rr_retries,
-
t_state.txn_conf->down_server_timeout);
- down) {
- char *url_str =
t_state.hdr_info.client_request.url_string_get_ref(nullptr);
- std::string_view host_name{t_state.unmapped_url.host_get()};
- swoc::bwprint(error_bw_buffer, "CONNECT : {::s} connecting to {} for
host='{}' url='{}' fail_count='{}' marking down",
-
swoc::bwf::Errno(t_state.current.server->connect_result),
t_state.current.server->dst_addr, host_name,
- swoc::bwf::FirstOf(url_str, "<none>"), fail_count);
- Log::error("%s", error_bw_buffer.c_str());
- SMDbg(dbg_ctl_http, "hostdb update marking IP: %s as down", addrbuf);
- ATS_PROBE2(hostdb_mark_ip_as_down, sm_id, addrbuf);
- } else {
- ATS_PROBE3(hostdb_inc_ip_failcount, sm_id, addrbuf, fail_count);
- SMDbg(dbg_ctl_http, "hostdb increment IP failcount %s to %d", addrbuf,
fail_count);
- }
- } else { // Clear the failure
- info->active->mark_up();
- }
+ if (info->active == nullptr) {
+ return;
+ }
+
+ char addrbuf[INET6_ADDRPORTSTRLEN];
+ ats_ip_nptop(&t_state.current.server->dst_addr.sa, addrbuf, sizeof(addrbuf));
+
+ const uint8_t max_connect_retries =
HttpTransact::origin_server_connect_attempts_max_retries(&t_state);
+ const ts_seconds fail_window = t_state.txn_conf->down_server_timeout;
+
+ // Mark the host DOWN only after every attempt has failed.
`max_connect_retries` counts only "retries", so the total attempt
+ // budget is `max_connect_retries + 1` (the initial connect plus each retry).
+ auto [down, fail_count] = info->active->increment_fail_count(time_down,
max_connect_retries + 1, fail_window);
+
+ if (down) {
+ Metrics::Counter::increment(http_rsb.down_server_no_requests);
+ char *url_str =
t_state.hdr_info.client_request.url_string_get_ref(nullptr);
+ std::string_view host_name{t_state.unmapped_url.host_get()};
+ swoc::bwprint(error_bw_buffer, "CONNECT : {::s} connecting to {} for
host='{}' url='{}' fail_count='{}' marking down",
+ swoc::bwf::Errno(t_state.current.server->connect_result),
t_state.current.server->dst_addr, host_name,
+ swoc::bwf::FirstOf(url_str, "<none>"), fail_count);
+ Log::error("%s", error_bw_buffer.c_str());
+ SMDbg(dbg_ctl_http, "hostdb update marking IP: %s as down", addrbuf);
+ ATS_PROBE2(hostdb_mark_ip_as_down, sm_id, addrbuf);
+ } else {
+ ATS_PROBE3(hostdb_inc_ip_failcount, sm_id, addrbuf, fail_count);
+ SMDbg(dbg_ctl_http, "hostdb increment IP failcount %s to %d", addrbuf,
fail_count);
}
-#ifdef DEBUG
- ink_assert(std::chrono::system_clock::now() +
t_state.txn_conf->down_server_timeout > time_down);
-#endif
}
void
diff --git a/src/proxy/http/HttpTransact.cc b/src/proxy/http/HttpTransact.cc
index 1037611b07..df56761a64 100644
--- a/src/proxy/http/HttpTransact.cc
+++ b/src/proxy/http/HttpTransact.cc
@@ -562,6 +562,41 @@ HttpTransact::is_server_negative_cached(State *s)
}
}
+/**
+ ATS has two configuration options controlling how many times it retries a
connection attempt against origin servers.
+
+ - proxy.config.http.connect_attempts_max_retries
+ - proxy.config.http.connect_attempts_max_retries_suspect_server
+
+ The choice is based on the state of the active HostDBInfo.
+
+ - HostDBInfo::State::UP: use proxy.config.http.connect_attempts_max_retries
+ - HostDBInfo::State::DOWN: no retry
+ - HostDBInfo::State::SUSPECT: use
proxy.config.http.connect_attempts_max_retries_suspect_server
+
+*/
+uint8_t
+HttpTransact::origin_server_connect_attempts_max_retries(State *s)
+{
+ HostDBInfo *active = s->dns_info.active;
+ if (active == nullptr) {
+ return 0;
+ }
+
+ switch (active->state(ts_clock::now(), s->txn_conf->down_server_timeout)) {
+ case HostDBInfo::State::UP:
+ return s->txn_conf->connect_attempts_max_retries;
+ case HostDBInfo::State::DOWN:
+ return 0;
+ case HostDBInfo::State::SUSPECT:
+ return s->txn_conf->connect_attempts_max_retries_suspect_server;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
inline static void
update_current_info(HttpTransact::CurrentInfo *into,
HttpTransact::ConnectionAttributes *from,
ResolveInfo::UpstreamResolveStyle who, bool
clear_retry_attempts)
@@ -974,22 +1009,6 @@ HttpTransact::TooEarly(State *s)
TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
}
-void
-HttpTransact::OriginDown(State *s)
-{
- TxnDbg(dbg_ctl_http_trans, "origin server is marked down");
- bootstrap_state_variables_from_request(s, &s->hdr_info.client_request);
- build_error_response(s, HTTPStatus::BAD_GATEWAY, "Origin Server Marked
Down", "connect#failed_connect");
- Metrics::Counter::increment(http_rsb.down_server_no_requests);
- char *url_str =
s->hdr_info.client_request.url_string_get_ref(nullptr);
- std::string_view host_name{s->unmapped_url.host_get()};
- swoc::bwprint(error_bw_buffer, "CONNECT: down server no request to {} for
host='{}' url='{}'", s->current.server->dst_addr,
- host_name, swoc::bwf::FirstOf(url_str, "<none>"));
- Log::error("%s", error_bw_buffer.c_str());
-
- TRANSACT_RETURN(StateMachineAction_t::SEND_ERROR_CACHE_NOOP, nullptr);
-}
-
void
HttpTransact::HandleBlindTunnel(State *s)
{
@@ -1969,6 +1988,9 @@ HttpTransact::OSDNSLookup(State *s)
build_error_response(s, HTTPStatus::INTERNAL_SERVER_ERROR, "Cannot
find server.", Dns_error_body);
log_msg = "looking up";
} else {
+ // HostDB has the record but every address is DOWN within
`down_server.cache_time`. This is a refusal-to-attempt
+ // rather than a true DNS failure; track it under
down_server_no_requests.
+ Metrics::Counter::increment(http_rsb.down_server_no_requests);
build_error_response(s, HTTPStatus::INTERNAL_SERVER_ERROR, "No valid
server.", "connect#all_down");
log_msg = "no valid server";
}
@@ -1998,7 +2020,8 @@ HttpTransact::OSDNSLookup(State *s)
// We've backed off from a client supplied address and found some
// HostDB addresses. We use those if they're different from the CTA.
// In all cases we now commit to client or HostDB for our source.
- if (s->dns_info.set_active(&s->current.server->dst_addr.sa) &&
s->dns_info.select_next_rr()) {
+ if (s->dns_info.set_active(&s->current.server->dst_addr.sa) &&
+ s->dns_info.select_next_rr(ts_clock::now(),
s->txn_conf->down_server_timeout)) {
s->dns_info.os_addr_style = ResolveInfo::OS_Addr::USE_HOSTDB;
} else {
// nothing else there, continue with CTA.
@@ -2687,6 +2710,7 @@ HttpTransact::CallOSDNSLookup(State *s)
} else {
s->cache_info.action = CacheAction_t::NO_ACTION;
}
+ error_log_connection_failure(s, s->current.state);
handle_server_connection_not_open(s);
} else {
TRANSACT_RETURN(StateMachineAction_t::DNS_LOOKUP, OSDNSLookup);
@@ -3882,6 +3906,7 @@ HttpTransact::handle_response_from_parent(State *s)
case ResolveInfo::HOST_NONE:
// Check if content can be served from cache
s->current.request_to = ResolveInfo::PARENT_PROXY;
+ error_log_connection_failure(s, s->current.state);
handle_server_connection_not_open(s);
break;
default:
@@ -3914,7 +3939,6 @@ HttpTransact::handle_response_from_server(State *s)
{
TxnDbg(dbg_ctl_http_trans, "(hrfs)");
HTTP_RELEASE_ASSERT(s->current.server == &s->server_info);
- unsigned max_connect_retries = 0;
// plugin call
s->server_info.state = s->current.state;
@@ -3933,6 +3957,7 @@ HttpTransact::handle_response_from_server(State *s)
TxnDbg(dbg_ctl_http_trans, "Error. congestion control -- congested.");
SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
s->set_connect_fail(EUSERS); // too many users
+ error_log_connection_failure(s, s->current.state);
handle_server_connection_not_open(s);
break;
case OPEN_RAW_ERROR:
@@ -3941,8 +3966,7 @@ HttpTransact::handle_response_from_server(State *s)
case INACTIVE_TIMEOUT:
case PARSE_ERROR:
case CONNECTION_CLOSED:
- case BAD_INCOMING_RESPONSE:
-
+ case BAD_INCOMING_RESPONSE: {
// Ensure cause_of_death_errno is set for all error states if not already
set.
// This prevents the assertion failure in retry_server_connection_not_open.
if (s->cause_of_death_errno == -UNKNOWN_INTERNAL_ERROR) {
@@ -3957,63 +3981,92 @@ HttpTransact::handle_response_from_server(State *s)
}
}
- if (is_server_negative_cached(s)) {
- max_connect_retries =
s->txn_conf->connect_attempts_max_retries_down_server - 1;
- } else {
- // server not yet negative cached - use default number of retries
- max_connect_retries = s->txn_conf->connect_attempts_max_retries;
- }
-
+ unsigned max_connect_retries = s->txn_conf->connect_attempts_max_retries;
TxnDbg(dbg_ctl_http_trans, "max_connect_retries: %d
s->current.retry_attempts: %d", max_connect_retries,
s->current.retry_attempts.get());
- if (is_request_retryable(s) && s->current.retry_attempts.get() <
max_connect_retries &&
- !HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
- // If this is a round robin DNS entry & we're tried configured
- // number of times, we should try another node
- if (ResolveInfo::OS_Addr::TRY_CLIENT == s->dns_info.os_addr_style) {
- // attempt was based on client supplied server address. Try again
using HostDB.
- // Allow DNS attempt
- s->dns_info.resolved_p = false;
- // See if we can get data from HostDB for this.
- s->dns_info.os_addr_style = ResolveInfo::OS_Addr::TRY_HOSTDB;
- // Force host resolution to have the same family as the client.
- // Because this is a transparent connection, we can't switch address
- // families - that is locked in by the client source address.
- ats_force_order_by_family(s->current.server->dst_addr.family(),
s->my_txn_conf().host_res_data.order);
- return CallOSDNSLookup(s);
- } else if (ResolveInfo::OS_Addr::USE_API == s->dns_info.os_addr_style &&
!s->api_server_addr_set_retried) {
- // Plugin set the server address via TSHttpTxnServerAddrSet(). Clear
resolution
- // state to allow the OS_DNS hook to be called again, giving the
plugin a chance
- // to set a different server address for retry (issue #12611).
- // Only retry once to avoid infinite loops if the plugin keeps setting
failing addresses.
- s->api_server_addr_set_retried = true;
- s->dns_info.resolved_p = false;
- s->dns_info.os_addr_style = ResolveInfo::OS_Addr::TRY_DEFAULT;
- // Clear the server request so it can be rebuilt for the new
destination
- s->hdr_info.server_request.destroy();
- TxnDbg(dbg_ctl_http_trans, "Retrying with plugin-set address,
returning to OS_DNS hook");
- return CallOSDNSLookup(s);
- } else {
- if ((s->txn_conf->connect_attempts_rr_retries > 0) &&
- ((s->current.retry_attempts.get() + 1) %
s->txn_conf->connect_attempts_rr_retries == 0)) {
- s->dns_info.select_next_rr();
+ // Bail out if the request is not retryable, the global retry cap is
reached, or we already have a usable response.
+ if (!is_request_retryable(s) || s->current.retry_attempts.get() >=
max_connect_retries ||
+ HttpTransact::is_response_valid(s, &s->hdr_info.server_response)) {
+ TxnDbg(dbg_ctl_http_trans, "Error. No more retries. %d/%d",
s->current.retry_attempts.get(), max_connect_retries);
+ SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
+ error_log_connection_failure(s, s->current.state);
+ s->state_machine->do_hostdb_update_if_necessary();
+ handle_server_connection_not_open(s);
+ break;
+ }
+
+ // Attempt was based on a client-supplied address. Re-resolve via HostDB.
+ if (ResolveInfo::OS_Addr::TRY_CLIENT == s->dns_info.os_addr_style) {
+ // Allow DNS attempt
+ s->dns_info.resolved_p = false;
+ // See if we can get data from HostDB for this.
+ s->dns_info.os_addr_style = ResolveInfo::OS_Addr::TRY_HOSTDB;
+ // Force host resolution to have the same family as the client.
+ // Because this is a transparent connection, we can't switch address
+ // families - that is locked in by the client source address.
+ ats_force_order_by_family(s->current.server->dst_addr.family(),
s->my_txn_conf().host_res_data.order);
+ return CallOSDNSLookup(s);
+ }
+
+ // Plugin set the server address via TSHttpTxnServerAddrSet(). Clear
resolution
+ // state to allow the OS_DNS hook to be called again, giving the plugin a
chance
+ // to set a different server address for retry (issue #12611).
+ // Only retry once to avoid infinite loops if the plugin keeps setting
failing addresses.
+ if (ResolveInfo::OS_Addr::USE_API == s->dns_info.os_addr_style &&
!s->api_server_addr_set_retried) {
+ s->api_server_addr_set_retried = true;
+ s->dns_info.resolved_p = false;
+ s->dns_info.os_addr_style = ResolveInfo::OS_Addr::TRY_DEFAULT;
+ // Clear the server request so it can be rebuilt for the new destination
+ s->hdr_info.server_request.destroy();
+ TxnDbg(dbg_ctl_http_trans, "Retrying with plugin-set address, returning
to OS_DNS hook");
+ return CallOSDNSLookup(s);
+ }
+
+ // Record the failure on the current active target.
+ error_log_connection_failure(s, s->current.state);
+ s->state_machine->do_hostdb_update_if_necessary();
+
+ // Decide between switching to the next round-robin member or staying on
the same target.
+ if ((s->txn_conf->connect_attempts_rr_retries > 0) &&
+ ((s->current.retry_attempts.get() + 1) %
s->txn_conf->connect_attempts_rr_retries == 0)) {
+ if (s->dns_info.select_next_rr(ts_clock::now(),
s->txn_conf->down_server_timeout)) {
+ // select_next_rr() only updates dns_info.active; change the dst_addr
too.
+ s->dns_info.addr.assign(s->dns_info.active->data.ip);
+ s->server_info.dst_addr.assign(s->dns_info.active->data.ip,
s->server_info.dst_addr.network_order_port());
+ if (dbg_ctl_http_trans.on()) {
+ ip_port_text_buffer addrbuf;
+ TxnDbg(dbg_ctl_http_trans, "switched to next round-robin upstream
addr=%s",
+ ats_ip_nptop(&s->server_info.dst_addr.sa, addrbuf,
sizeof(addrbuf)));
}
- retry_server_connection_not_open(s, s->current.state,
max_connect_retries);
- TxnDbg(dbg_ctl_http_trans, "Error. Retrying...");
- s->next_action = how_to_open_connection(s);
+ } else {
+ TxnDbg(dbg_ctl_http_trans, "No round-robin targets available, retrying
current upstream if possible");
}
- } else {
- error_log_connection_failure(s, s->current.state);
- TxnDbg(dbg_ctl_http_trans, "Error. No more retries.");
+ }
+
+ // The active target (HostDB) may be SUSPECT state, so re-evaluate the
retry limit.
+ // Skip when there is no HostDBInfo (e.g. USE_CLIENT / USE_API) and keep
the configured baseline.
+ if (s->dns_info.active != nullptr) {
+ max_connect_retries = origin_server_connect_attempts_max_retries(s);
+ }
+ if (max_connect_retries <= s->current.retry_attempts.get()) {
+ TxnDbg(dbg_ctl_http_trans, "Per-host retries exhausted. Giving up.
%d/%d", s->current.retry_attempts.get(),
+ max_connect_retries);
SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
handle_server_connection_not_open(s);
+ break;
}
+
+ TxnDbg(dbg_ctl_http_trans, "Error. Retrying...");
+ retry_server_connection_not_open(s, max_connect_retries);
+ s->next_action = how_to_open_connection(s);
break;
+ }
case ACTIVE_TIMEOUT:
TxnDbg(dbg_ctl_http_trans, "[hrfs] connection not alive");
SET_VIA_STRING(VIA_DETAIL_SERVER_CONNECT, VIA_DETAIL_SERVER_FAILURE);
s->set_connect_fail(ETIMEDOUT);
+ s->state_machine->do_hostdb_update_if_necessary();
handle_server_connection_not_open(s);
break;
default:
@@ -4062,15 +4115,13 @@ HttpTransact::error_log_connection_failure(State *s,
ServerState_t conn_state)
//
///////////////////////////////////////////////////////////////////////////////
void
-HttpTransact::retry_server_connection_not_open(State *s, ServerState_t
conn_state, unsigned max_retries)
+HttpTransact::retry_server_connection_not_open(State *s, unsigned max_retries)
{
ink_assert(s->current.state != CONNECTION_ALIVE);
ink_assert(s->current.state != ACTIVE_TIMEOUT);
ink_assert(s->current.retry_attempts.get() < max_retries);
ink_assert(s->cause_of_death_errno != -UNKNOWN_INTERNAL_ERROR);
- error_log_connection_failure(s, conn_state);
-
//////////////////////////////////////////////
// disable keep-alive for request and retry //
//////////////////////////////////////////////
@@ -4104,9 +4155,6 @@ HttpTransact::handle_server_connection_not_open(State *s)
SET_VIA_STRING(VIA_SERVER_RESULT, VIA_SERVER_ERROR);
Metrics::Counter::increment(http_rsb.broken_server_connections);
- // Fire off a hostdb update to mark the server as down
- s->state_machine->do_hostdb_update_if_necessary();
-
switch (s->cache_info.action) {
case CacheAction_t::UPDATE:
case CacheAction_t::SERVE:
diff --git a/src/records/RecordsConfig.cc b/src/records/RecordsConfig.cc
index 4586f039a2..6fa2c18bc4 100644
--- a/src/records/RecordsConfig.cc
+++ b/src/records/RecordsConfig.cc
@@ -496,11 +496,13 @@ static constexpr RecordElement RecordsConfig[] =
// ##################################
// # origin server connect attempts #
// ##################################
- {RECT_CONFIG, "proxy.config.http.connect_attempts_max_retries", RECD_INT,
"3", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+ {RECT_CONFIG, "proxy.config.http.connect_attempts_max_retries", RECD_INT,
"3", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-254]", RECA_NULL}
,
- {RECT_CONFIG, "proxy.config.http.connect_attempts_max_retries_down_server",
RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+ {RECT_CONFIG, "proxy.config.http.connect_attempts_max_retries_down_server",
RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-254]", RECA_NULL}
,
- {RECT_CONFIG, "proxy.config.http.connect_attempts_rr_retries", RECD_INT,
"3", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
+ {RECT_CONFIG,
"proxy.config.http.connect_attempts_max_retries_suspect_server", RECD_INT, "1",
RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-254]", RECA_NULL}
+ ,
+ {RECT_CONFIG, "proxy.config.http.connect_attempts_rr_retries", RECD_INT,
"3", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-254]", RECA_NULL}
,
{RECT_CONFIG, "proxy.config.http.connect_attempts_timeout", RECD_INT, "30",
RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL}
,
diff --git a/tests/gold_tests/autest-site/verifier_client.test.ext
b/tests/gold_tests/autest-site/verifier_client.test.ext
index 53f0f5f269..60ca394227 100755
--- a/tests/gold_tests/autest-site/verifier_client.test.ext
+++ b/tests/gold_tests/autest-site/verifier_client.test.ext
@@ -35,7 +35,8 @@ def _configure_client(
verbose=True,
other_args='',
run_parallel=False,
- context=None):
+ context=None,
+ poll_timeout=None):
"""
Configure the process for running the verifier-client.
@@ -136,6 +137,9 @@ def _configure_client(
if keys is not None:
command += f" --keys {keys}"
+ if poll_timeout is not None:
+ command += f" --poll-timeout {poll_timeout}"
+
# Generally we prefer the deterministic behavior of a single thread where
# each connection is processed sequentially.
if not run_parallel and 'thread-limit' not in command:
@@ -161,7 +165,8 @@ def AddVerifierClientProcess(
verbose=True,
other_args='',
run_parallel=False,
- context=None):
+ context=None,
+ poll_timeout=None):
"""
Set the Default process of the test run to a verifier-client Process.
@@ -198,6 +203,10 @@ def AddVerifierClientProcess(
Template strings support $-based substitutions in the replay
file.
You can refer to
https://docs.python.org/3/library/string.html#template-strings
for more information how to add template strings to the
replay file.
+
+ poll_timeout: (int) The poll timeout in milliseconds passed to
+ verifier-client via --poll-timeout. Defaults to None which leaves
the
+ verifier-client default (3000 ms) in place.
Returns:
The newly constructed verifier-client for the test run, which is also
the
Default Process of the test run.
@@ -213,7 +222,7 @@ def AddVerifierClientProcess(
p = run.Processes.Default
_configure_client(
run, p, name, replay_path, http_ports, https_ports, http3_ports, keys,
ssl_cert, ca_cert, verbose, other_args, run_parallel,
- context)
+ context, poll_timeout)
return p
diff --git
a/tests/gold_tests/connect_down_policy/replay/connect_down_policy_4.replay.yaml
b/tests/gold_tests/connect_down_policy/replay/connect_down_policy_4.replay.yaml
index 554e90d138..45fe1d8e5d 100644
---
a/tests/gold_tests/connect_down_policy/replay/connect_down_policy_4.replay.yaml
+++
b/tests/gold_tests/connect_down_policy/replay/connect_down_policy_4.replay.yaml
@@ -48,7 +48,7 @@ autest:
proxy.config.http.connect.down.policy: 4
proxy.config.http.connect_attempts_rr_retries: 0
proxy.config.http.connect_attempts_max_retries: 0
- proxy.config.http.connect_attempts_max_retries_down_server: 0
+ proxy.config.http.connect_attempts_max_retries_suspect_server: 0
proxy.config.http.connect_attempts_timeout: 1
proxy.config.http.down_server.cache_time: 5
diff --git a/tests/gold_tests/dns/connect_attempts.test.py
b/tests/gold_tests/dns/connect_attempts.test.py
index d46cb32d3d..e5b572d366 100644
--- a/tests/gold_tests/dns/connect_attempts.test.py
+++ b/tests/gold_tests/dns/connect_attempts.test.py
@@ -21,6 +21,11 @@ Test.Summary = '''
Verify Origin Server Connect Attempts Behavior
'''
+# Single DNS Record
+# max_retries & down_server
+Test.ATSReplayTest(replay_file="replay/connect_attempts_single_max_retries.replay.yaml")
+
+# Multiple DNS Records
# No retry
Test.ATSReplayTest(replay_file="replay/connect_attempts_rr_no_retry.replay.yaml")
diff --git a/tests/gold_tests/dns/dns_host_down.test.py
b/tests/gold_tests/dns/dns_host_down.test.py
index 80b59e0fb8..295100c2fd 100644
--- a/tests/gold_tests/dns/dns_host_down.test.py
+++ b/tests/gold_tests/dns/dns_host_down.test.py
@@ -73,9 +73,23 @@ class DownCachedOriginServerTest:
self._ts.Disk.error_log.Content = Testers.ContainsExpression(
"/dns/mark/down' fail_count='1' marking down", "host should be
marked down")
+ # Verify down_server_no_requests metric is incremented:
+ # - once when the first request marks the origin DOWN (502)
+ # - once when the second request is rejected because HostDB has no live
address (500)
+ def _test_down_server_no_requests_metric(self):
+ tr = Test.AddTestRun('Check proxy.process.http.down_server.no_requests
metric')
+ tr.Processes.Default.Command = 'traffic_ctl metric get
proxy.process.http.down_server.no_requests'
+ tr.Processes.Default.Env = self._ts.Env
+ tr.Processes.Default.ReturnCode = 0
+ tr.Processes.Default.Streams.All = Testers.ContainsExpression(
+ 'proxy.process.http.down_server.no_requests 2',
+ 'down_server.no_requests should be 2 (mark-down on first txn,
no-live-address on second)')
+ tr.StillRunningAfter = self._ts
+
def run(self):
self._test_host_mark_down()
self._test_error_log()
+ self._test_down_server_no_requests_metric()
DownCachedOriginServerTest().run()
diff --git
a/tests/gold_tests/dns/gold/connect_attempts_rr_max_retries_error_log.gold
b/tests/gold_tests/dns/gold/connect_attempts_rr_max_retries_error_log.gold
index 2172f69d46..bc2cbc1c80 100644
--- a/tests/gold_tests/dns/gold/connect_attempts_rr_max_retries_error_log.gold
+++ b/tests/gold_tests/dns/gold/connect_attempts_rr_max_retries_error_log.gold
@@ -1,8 +1,8 @@
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 `` retry_attempts=0
url='http://backend.example.com:``/path/'
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 `` retry_attempts=1
url='http://backend.example.com:``/path/'
-`` CONNECT : `` connecting to 0.0.0.1:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='1' marking down
+`` CONNECT : `` connecting to 0.0.0.1:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='2' marking down
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=1 `` retry_attempts=0
url='http://backend.example.com:``/path/'
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=1 `` retry_attempts=1
url='http://backend.example.com:``/path/'
-`` CONNECT : `` connecting to 0.0.0.2:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='1' marking down
+`` CONNECT : `` connecting to 0.0.0.2:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='2' marking down
`` DNS Error: no valid server http://backend.example.com:``/path/
``
diff --git
a/tests/gold_tests/dns/gold/connect_attempts_rr_retries_error_log.gold
b/tests/gold_tests/dns/gold/connect_attempts_rr_retries_error_log.gold
index c835cd3fa5..a4e061a67d 100644
--- a/tests/gold_tests/dns/gold/connect_attempts_rr_retries_error_log.gold
+++ b/tests/gold_tests/dns/gold/connect_attempts_rr_retries_error_log.gold
@@ -1,8 +1,9 @@
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 connection_result=`` error=`` retry_attempts=0
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=0 connection_result=`` error=`` retry_attempts=1
url='http://backend.example.com:``/path/'
`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=1 connection_result=`` error=`` retry_attempts=0
url='http://backend.example.com:``/path/'
`` CONNECT : `` connecting to 0.0.0.1:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='2' marking down
-`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=2 connection_result=`` error=`` retry_attempts=0
url='http://backend.example.com:``/path/'
-`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=3 connection_result=`` error=`` retry_attempts=0
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=1 connection_result=`` error=`` retry_attempts=1
url='http://backend.example.com:``/path/'
`` CONNECT : `` connecting to 0.0.0.2:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='2' marking down
`` DNS Error: no valid server http://backend.example.com:``/path/
-``
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=3 connection_result=`` error=`` retry_attempts=0
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.2:`` for
host='example.com' sm_id=3 connection_result=`` error=`` retry_attempts=1
url='http://backend.example.com:``/path/'
diff --git
a/tests/gold_tests/dns/gold/connect_attempts_single_max_retries_error_log.gold
b/tests/gold_tests/dns/gold/connect_attempts_single_max_retries_error_log.gold
new file mode 100644
index 0000000000..5aef6b9655
--- /dev/null
+++
b/tests/gold_tests/dns/gold/connect_attempts_single_max_retries_error_log.gold
@@ -0,0 +1,9 @@
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 `` retry_attempts=0
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 `` retry_attempts=1
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=0 `` retry_attempts=2
url='http://backend.example.com:``/path/'
+`` CONNECT : `` connecting to 0.0.0.1:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='3' marking down
+`` DNS Error: no valid server http://backend.example.com:``/path/
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=2 `` retry_attempts=0
url='http://backend.example.com:``/path/'
+`` CONNECT: attempt fail [CONNECTION_ERROR] to 0.0.0.1:`` for
host='example.com' sm_id=2 `` retry_attempts=1
url='http://backend.example.com:``/path/'
+`` CONNECT : `` connecting to 0.0.0.1:`` for host='example.com'
url='http://backend.example.com:``/path/' fail_count='2' marking down
+`` DNS Error: no valid server http://backend.example.com:``/path/
diff --git
a/tests/gold_tests/dns/replay/connect_attempts_rr_max_retries.replay.yaml
b/tests/gold_tests/dns/replay/connect_attempts_rr_max_retries.replay.yaml
index b1c918ab2c..834c60fb91 100644
--- a/tests/gold_tests/dns/replay/connect_attempts_rr_max_retries.replay.yaml
+++ b/tests/gold_tests/dns/replay/connect_attempts_rr_max_retries.replay.yaml
@@ -41,7 +41,7 @@ autest:
proxy.config.diags.debug.tags: 'http|hostdb|dns'
proxy.config.http.connect_attempts_rr_retries: 0
proxy.config.http.connect_attempts_max_retries: 1
- proxy.config.http.connect_attempts_max_retries_down_server: 0
+ proxy.config.http.connect_attempts_max_retries_suspect_server: 0
proxy.config.http.connect_attempts_timeout: 1
proxy.config.http.down_server.cache_time: 10
diff --git
a/tests/gold_tests/dns/replay/connect_attempts_rr_no_retry.replay.yaml
b/tests/gold_tests/dns/replay/connect_attempts_rr_no_retry.replay.yaml
index b0ec1819eb..258653fbb8 100644
--- a/tests/gold_tests/dns/replay/connect_attempts_rr_no_retry.replay.yaml
+++ b/tests/gold_tests/dns/replay/connect_attempts_rr_no_retry.replay.yaml
@@ -41,7 +41,7 @@ autest:
proxy.config.diags.debug.tags: 'http|hostdb|dns'
proxy.config.http.connect_attempts_rr_retries: 0
proxy.config.http.connect_attempts_max_retries: 0
- proxy.config.http.connect_attempts_max_retries_down_server: 0
+ proxy.config.http.connect_attempts_max_retries_suspect_server: 0
proxy.config.http.connect_attempts_timeout: 1
proxy.config.http.down_server.cache_time: 5
diff --git
a/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
b/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
index 0d040345ff..971e623ff3 100644
--- a/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
+++ b/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
@@ -39,11 +39,11 @@ autest:
records_config:
proxy.config.diags.debug.enabled: 1
proxy.config.diags.debug.tags: 'http|hostdb|dns'
- proxy.config.http.connect_attempts_rr_retries: 2
- proxy.config.http.connect_attempts_max_retries: 0
- proxy.config.http.connect_attempts_max_retries_down_server: 0
+ proxy.config.http.connect_attempts_rr_retries: 1
+ proxy.config.http.connect_attempts_max_retries: 1
+ proxy.config.http.connect_attempts_max_retries_suspect_server: 1
proxy.config.http.connect_attempts_timeout: 1
- proxy.config.http.down_server.cache_time: 10
+ proxy.config.http.down_server.cache_time: 3
remap_config:
- from: "http://example.com/"
@@ -55,7 +55,9 @@ autest:
sessions:
- transactions:
- # try 0.0.0.1
+ # Both 0.0.0.1 and 0.0.0.2 are UP. ATS tries one host, then rr_retries to the
+ # other (connect_attempts_rr_retries=1). Both attempts fail, so the client
+ # gets 502. Each host's fail_count is now 1.
- client-request:
method: GET
url: /path/
@@ -73,7 +75,8 @@ sessions:
proxy-response:
status: 502
- # try 0.0.0.1 again
+ # Same round-robin path as above. After this attempt each host's fail_count
+ # reaches connect_attempts_max_retries + 1 (=2), so both are marked DOWN.
- client-request:
method: GET
url: /path/
@@ -91,7 +94,8 @@ sessions:
proxy-response:
status: 502
- # try 0.0.0.2
+ # Within down_server.cache_time (3s): both hosts are still cached as DOWN, so
+ # ATS skips the connect attempts entirely and returns 500.
- client-request:
method: GET
url: /path/
@@ -106,46 +110,11 @@ sessions:
status: 200
reason: OK
- proxy-response:
- status: 502
-
- # try 0.0.0.2 again
- - client-request:
- method: GET
- url: /path/
- version: '1.1'
- headers:
- fields:
- - [Host, example.com]
- - [uuid, 4]
-
- # should not hit
- server-response:
- status: 200
- reason: OK
-
- proxy-response:
- status: 502
-
- # The request is expected to hit the down_server cache and immediately
receive a 500 response.
- - client-request:
- method: GET
- url: /path/
- version: '1.1'
- headers:
- fields:
- - [Host, example.com]
- - [uuid, 10]
-
- # should not hit
- server-response:
- status: 200
- reason: OK
-
proxy-response:
status: 500
- # when down_server.cache_time is expired, try connect attempts
+ # After the 5s delay, down_server.cache_time (3s) has expired. ATS tries both
+ # hosts again via round-robin; both still fail, so the client gets 502.
- client-request:
method: GET
url: /path/
@@ -154,7 +123,7 @@ sessions:
fields:
- [Host, example.com]
- [uuid, 20]
- delay: 10s
+ delay: 5s
# should not hit
server-response:
diff --git
a/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
b/tests/gold_tests/dns/replay/connect_attempts_single_max_retries.replay.yaml
similarity index 63%
copy from tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
copy to
tests/gold_tests/dns/replay/connect_attempts_single_max_retries.replay.yaml
index 0d040345ff..85285c551a 100644
--- a/tests/gold_tests/dns/replay/connect_attempts_rr_retries.replay.yaml
+++
b/tests/gold_tests/dns/replay/connect_attempts_single_max_retries.replay.yaml
@@ -19,31 +19,33 @@ meta:
# Configuration section for autest integration
autest:
- description: 'Verify connect attempts behavior - round robin'
+ description: 'Verify connect attempts behavior - no round-robin (single
host)'
dns:
- name: 'dns-rrr'
- records: {"backend.example.com": ["0.0.0.1", "0.0.0.2"]}
+ name: 'dns-single-retries'
+ records: {"backend.example.com": ["0.0.0.1"]}
server:
- name: 'server-rrr'
+ name: 'server-single-retries'
client:
- name: 'client-rrr'
+ name: 'client-single-retries'
+ process_config:
+ poll_timeout: 10000 # ms
ats:
- name: 'ts-rrr'
+ name: 'ts-single-retries'
process_config:
enable_cache: false
records_config:
proxy.config.diags.debug.enabled: 1
proxy.config.diags.debug.tags: 'http|hostdb|dns'
- proxy.config.http.connect_attempts_rr_retries: 2
- proxy.config.http.connect_attempts_max_retries: 0
- proxy.config.http.connect_attempts_max_retries_down_server: 0
+ proxy.config.http.connect_attempts_rr_retries: 99 # make sure this
doesn't affect this case
+ proxy.config.http.connect_attempts_max_retries: 2
+ proxy.config.http.connect_attempts_max_retries_suspect_server: 1
proxy.config.http.connect_attempts_timeout: 1
- proxy.config.http.down_server.cache_time: 10
+ proxy.config.http.down_server.cache_time: 3
remap_config:
- from: "http://example.com/"
@@ -51,11 +53,12 @@ autest:
log_validation:
error_log:
- gold_file: "gold/connect_attempts_rr_retries_error_log.gold"
+ gold_file: "gold/connect_attempts_single_max_retries_error_log.gold"
sessions:
- transactions:
- # try 0.0.0.1
+ # First request: ATS attempts 3 times (1 initial + 2 retries) to connect to
0.0.0.1.
+ # The server is marked as down and ATS returns 502.
- client-request:
method: GET
url: /path/
@@ -73,7 +76,8 @@ sessions:
proxy-response:
status: 502
- # try 0.0.0.1 again
+ # Second request: within down_server.cache_time=3s so the server is still
marked down.
+ # ATS skips the connection attempt entirely and returns 500.
- client-request:
method: GET
url: /path/
@@ -89,9 +93,11 @@ sessions:
reason: OK
proxy-response:
- status: 502
+ status: 500
- # try 0.0.0.2
+ # Third request: delayed 5s so the down_server.cache_time=3s has expired.
+ # ATS attempts 2 times (1 initial + 1 retries) to connect to 0.0.0.1.
+ # The server is marked as down again and ATS returns 502.
- client-request:
method: GET
url: /path/
@@ -100,6 +106,7 @@ sessions:
fields:
- [Host, example.com]
- [uuid, 3]
+ delay: 5s
# should not hit
server-response:
@@ -109,7 +116,8 @@ sessions:
proxy-response:
status: 502
- # try 0.0.0.2 again
+ # Fourth request: within down_server.cache_time=3s so the server is still
marked down.
+ # ATS skips the connection attempt entirely and returns 500.
- client-request:
method: GET
url: /path/
@@ -119,47 +127,8 @@ sessions:
- [Host, example.com]
- [uuid, 4]
- # should not hit
server-response:
status: 200
- reason: OK
-
- proxy-response:
- status: 502
-
- # The request is expected to hit the down_server cache and immediately
receive a 500 response.
- - client-request:
- method: GET
- url: /path/
- version: '1.1'
- headers:
- fields:
- - [Host, example.com]
- - [uuid, 10]
-
- # should not hit
- server-response:
- status: 200
- reason: OK
proxy-response:
status: 500
-
- # when down_server.cache_time is expired, try connect attempts
- - client-request:
- method: GET
- url: /path/
- version: '1.1'
- headers:
- fields:
- - [Host, example.com]
- - [uuid, 20]
- delay: 10s
-
- # should not hit
- server-response:
- status: 200
- reason: OK
-
- proxy-response:
- status: 502