This is an automated email from the ASF dual-hosted git repository. zwoop pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.0.x by this push: new e95503f Add support for a simple_server_retry_responses list (#6605) e95503f is described below commit e95503f1c6c7311d5f7ba9dda5466512b1bb54b4 Author: Evan Zelkowitz <e...@apache.org> AuthorDate: Thu Apr 2 08:15:35 2020 -0700 Add support for a simple_server_retry_responses list (#6605) This adds support for simple_server_retry_responses to allow the user to set a list of 4xx reponse codes which trigger a simple retry, instead of the current functionality which will only trigger on a 404. This mimics the unavailable responses list in the same manner except for the 4xx simple retry case (cherry picked from commit 0d22ab057a42cf3fbc0b782479e964df2c1c8047) --- doc/admin-guide/files/parent.config.en.rst | 10 ++++++- proxy/ParentSelection.cc | 42 ++++++++++++++++++++++++++++++ proxy/ParentSelection.h | 29 ++++++++++++++++++++- proxy/http/HttpTransact.cc | 29 +++++++++++++++++---- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/doc/admin-guide/files/parent.config.en.rst b/doc/admin-guide/files/parent.config.en.rst index 83584ea..c7fc123 100644 --- a/doc/admin-guide/files/parent.config.en.rst +++ b/doc/admin-guide/files/parent.config.en.rst @@ -207,7 +207,8 @@ The following list shows the possible actions and their allowed values. .. _parent-config-format-parent-retry: ``parent_retry`` - - ``simple_retry`` - If the parent origin server returns a 404 response on a request + - ``simple_retry`` - If the parent returns a 404 response or if the response matches + a list of http 4xx responses defined in ``simple_server_retry_responses`` on a request a new parent is selected and the request is retried. The number of retries is controlled by ``max_simple_retries`` which is set to 1 by default. - ``unavailable_server_retry`` - If the parent returns a 503 response or if the response matches @@ -216,6 +217,13 @@ The following list shows the possible actions and their allowed values. retries is controlled by ``max_unavailable_server_retries`` which is set to 1 by default. - ``both`` - This enables both ``simple_retry`` and ``unavailable_server_retry`` as described above. +.. _parent-config-format-simple-server-retry-responses: + +``simple_server_retry_responses`` + If ``parent_retry`` is set to either ``simple_retry`` or ``both``, this parameter is a comma separated list of + http 4xx response codes that will invoke the ``simple_retry`` described in the ``parent_retry`` section. By + default, ``simple_server_retry_responses`` is set to 404. + .. _parent-config-format-unavailable-server-retry-responses: ``unavailable_server_retry_responses`` diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc index 2589ce9..1b6a861 100644 --- a/proxy/ParentSelection.cc +++ b/proxy/ParentSelection.cc @@ -350,6 +350,33 @@ UnavailableServerResponseCodes::UnavailableServerResponseCodes(char *val) std::sort(codes.begin(), codes.end()); } +SimpleRetryResponseCodes::SimpleRetryResponseCodes(char *val) +{ + Tokenizer pTok(", \t\r"); + int numTok = 0, c; + + if (val == nullptr) { + Warning("SimpleRetryResponseCodes - simple_server_retry_responses is null loading default 404 code."); + codes.push_back(HTTP_STATUS_NOT_FOUND); + return; + } + numTok = pTok.Initialize(val, SHARE_TOKS); + if (numTok == 0) { + c = atoi(val); + if (c > 399 && c < 500) { + codes.push_back(HTTP_STATUS_NOT_FOUND); + } + } + for (int i = 0; i < numTok; i++) { + c = atoi(pTok[i]); + if (c > 399 && c < 500) { + Debug("parent_select", "loading simple response code: %d", c); + codes.push_back(c); + } + } + std::sort(codes.begin(), codes.end()); +} + void ParentRecord::PreProcessParents(const char *val, const int line_num, char *buf, size_t len) { @@ -694,6 +721,9 @@ ParentRecord::Init(matcher_line *line_info) } else if (strcasecmp(label, "unavailable_server_retry_responses") == 0 && unavailable_server_retry_responses == nullptr) { unavailable_server_retry_responses = new UnavailableServerResponseCodes(val); used = true; + } else if (strcasecmp(label, "simple_server_retry_responses") == 0 && simple_server_retry_responses == nullptr) { + simple_server_retry_responses = new SimpleRetryResponseCodes(val); + used = true; } else if (strcasecmp(label, "max_simple_retries") == 0) { int v = atoi(val); if (v >= 1 && v < MAX_SIMPLE_RETRIES) { @@ -750,6 +780,18 @@ ParentRecord::Init(matcher_line *line_info) unavailable_server_retry_responses = new UnavailableServerResponseCodes(nullptr); } + // delete simple_server_retry_responses if simple_retry is not enabled. + if (simple_server_retry_responses != nullptr && !(parent_retry & PARENT_RETRY_SIMPLE)) { + Warning("%s ignore simple_server_Retry_responses directive on line %d, as simple_server_retry is not enabled.", modulePrefix, + line_num); + delete simple_server_retry_responses; + simple_server_retry_responses = nullptr; + } else if (simple_server_retry_responses == nullptr && (parent_retry & PARENT_RETRY_SIMPLE)) { + // initialize simple server respones codes to the default value if simple_retry is enabled. + Warning("%s initializing SimpleRetryResponseCodes on line %d to 404 default.", modulePrefix, line_num); + simple_server_retry_responses = new SimpleRetryResponseCodes(nullptr); + } + if (this->parents == nullptr && go_direct == false) { return Result::failure("%s No parent specified in %s at line %d", modulePrefix, ts::filename::PARENT, line_num); } diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h index 7d1d621..1e46485 100644 --- a/proxy/ParentSelection.h +++ b/proxy/ParentSelection.h @@ -92,6 +92,19 @@ private: std::vector<int> codes; }; +struct SimpleRetryResponseCodes { + SimpleRetryResponseCodes(char *val); + ~SimpleRetryResponseCodes(){}; + + bool + contains(int code) + { + return binary_search(codes.begin(), codes.end(), code); + } + +private: + std::vector<int> codes; +}; // struct pRecord // // A record for an individual parent @@ -145,6 +158,7 @@ public: bool parent_is_proxy = true; ParentSelectionStrategy *selection_strategy = nullptr; UnavailableServerResponseCodes *unavailable_server_retry_responses = nullptr; + SimpleRetryResponseCodes *simple_server_retry_responses = nullptr; ParentRetry_t parent_retry = PARENT_RETRY_NONE; int max_simple_retries = 1; int max_unavailable_server_retries = 1; @@ -242,7 +256,20 @@ struct ParentResult { bool response_is_retryable(HTTPStatus response_code) const { - return (retry_type() & PARENT_RETRY_UNAVAILABLE_SERVER) && rec->unavailable_server_retry_responses->contains(response_code); + Debug("parent_select", "In response_is_retryable, code: %d", response_code); + if (retry_type() == PARENT_RETRY_BOTH) { + Debug("parent_select", "Saw retry both"); + return (rec->unavailable_server_retry_responses->contains(response_code) || + rec->simple_server_retry_responses->contains(response_code)); + } else if (retry_type() == PARENT_RETRY_UNAVAILABLE_SERVER) { + Debug("parent_select", "Saw retry unavailable server"); + return rec->unavailable_server_retry_responses->contains(response_code); + } else if (retry_type() == PARENT_RETRY_SIMPLE) { + Debug("parent_select", "Saw retry simple retry"); + return rec->simple_server_retry_responses->contains(response_code); + } else { + return false; + } } bool diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc index 8bfa521..d9997cd 100644 --- a/proxy/http/HttpTransact.cc +++ b/proxy/http/HttpTransact.cc @@ -280,6 +280,26 @@ is_localhost(const char *name, int len) return (len == (sizeof(local) - 1)) && (memcmp(name, local, len) == 0); } +inline static bool +is_response_simple_code(HTTPStatus response_code) +{ + if (static_cast<unsigned int>(response_code) < 400 || static_cast<unsigned int>(response_code) > 499) { + return false; + } + + return true; +} + +inline static bool +is_response_unavailable_code(HTTPStatus response_code) +{ + if (static_cast<unsigned int>(response_code) < 500 || static_cast<unsigned int>(response_code) > 599) { + return false; + } + + return true; +} + inline static void simple_or_unavailable_server_retry(HttpTransact::State *s) { @@ -288,11 +308,10 @@ simple_or_unavailable_server_retry(HttpTransact::State *s) TxnDebug("http_trans", "[simple_or_unavailabe_server_retry] server_response = %d, simple_retry_attempts: %d, numParents:%d ", server_response, s->current.simple_retry_attempts, numParents(s)); - // simple retry is enabled, 0x1 - if ((retry_type(s) & PARENT_RETRY_SIMPLE) && s->current.simple_retry_attempts < max_retries(s, PARENT_RETRY_SIMPLE) && - server_response == HTTP_STATUS_NOT_FOUND) { - TxnDebug("http_trans", "RECEIVED A SIMPLE RETRY RESPONSE"); + if ((retry_type(s) & PARENT_RETRY_SIMPLE) && is_response_simple_code(server_response) && + s->current.simple_retry_attempts < max_retries(s, PARENT_RETRY_SIMPLE) && response_is_retryable(s, server_response)) { + TxnDebug("parent_select", "RECEIVED A SIMPLE RETRY RESPONSE"); if (s->current.simple_retry_attempts < numParents(s)) { s->current.state = HttpTransact::PARENT_RETRY; s->current.retry_type = PARENT_RETRY_SIMPLE; @@ -303,7 +322,7 @@ simple_or_unavailable_server_retry(HttpTransact::State *s) } } // unavailable server retry is enabled 0x2 - else if ((retry_type(s) & PARENT_RETRY_UNAVAILABLE_SERVER) && + else if ((retry_type(s) & PARENT_RETRY_UNAVAILABLE_SERVER) && is_response_unavailable_code(server_response) && s->current.unavailable_server_retry_attempts < max_retries(s, PARENT_RETRY_UNAVAILABLE_SERVER) && response_is_retryable(s, server_response)) { TxnDebug("parent_select", "RECEIVED A PARENT_RETRY_UNAVAILABLE_SERVER RESPONSE");