BUG/MINOR: http-ana: Adjust the server status before the L7 retries

The server status must be adjusted, if necessary, at each retry. It is
properly performed when "obersve layer4" directive is set. But for the layer
7, only the last attempt was considered.

When the L7 retries were implemented, all retries were added before the
server status adjutement. So only the last attempt was considered. To fix
the issue, we must adjut the server status first, and then try to perform a
L7 retry.

This patch should fix the issue #2679. It must be backported to all stable
versions.
This commit is contained in:
Christopher Faulet 2024-11-19 16:33:55 +01:00
parent 5c15899410
commit 2a5da31cce
1 changed files with 35 additions and 27 deletions

View File

@ -1234,8 +1234,11 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
htx = htxbuf(&rep->buf);
/* Parsing errors are caught here */
if (htx->flags & HTX_FL_PARSING_ERROR)
if (htx->flags & HTX_FL_PARSING_ERROR) {
if (objt_server(s->target))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
goto return_bad_res;
}
if (htx->flags & HTX_FL_PROCESSING_ERROR)
goto return_int_err;
@ -1257,6 +1260,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
if (s->scb->flags & SC_FL_ERROR) {
struct connection *conn = sc_conn(s->scb);
if (!(s->flags & SF_SRV_REUSED) && objt_server(s->target))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_READ_ERROR);
if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_DISCONNECTED) &&
@ -1279,10 +1284,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
goto abort_keep_alive;
_HA_ATOMIC_INC(&s->be->be_counters.failed_resp);
if (objt_server(s->target)) {
if (objt_server(s->target))
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.failed_resp);
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_READ_ERROR);
}
/* if the server refused the early data, just send a 425 */
if (conn && conn->err_code == CO_ER_SSL_EARLY_FAILED)
@ -1306,6 +1309,9 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* 2: read timeout : return a 504 to the client. */
else if (rep->flags & CF_READ_TIMEOUT) {
if (objt_server(s->target))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_READ_TIMEOUT);
if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_TIMEOUT)) {
if (co_data(rep) || do_l7_retry(s, s->scb) == 0) {
@ -1315,10 +1321,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
}
}
_HA_ATOMIC_INC(&s->be->be_counters.failed_resp);
if (objt_server(s->target)) {
if (objt_server(s->target))
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.failed_resp);
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_READ_TIMEOUT);
}
txn->status = 504;
stream_inc_http_fail_ctr(s);
@ -1360,6 +1364,9 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
/* 4: close from server, capture the response if the server has started to respond */
else if (s->scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) {
if (!(s->flags & SF_SRV_REUSED) && objt_server(s->target))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_BROKEN_PIPE);
if ((txn->flags & TX_L7_RETRY) &&
(s->be->retry_type & PR_RE_DISCONNECTED)) {
if (co_data(rep) || do_l7_retry(s, s->scb) == 0) {
@ -1373,10 +1380,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
goto abort_keep_alive;
_HA_ATOMIC_INC(&s->be->be_counters.failed_resp);
if (objt_server(s->target)) {
if (objt_server(s->target))
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.failed_resp);
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_BROKEN_PIPE);
}
txn->status = 502;
stream_inc_http_fail_ctr(s);
@ -1427,6 +1432,17 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
BUG_ON(htx_get_first_type(htx) != HTX_BLK_RES_SL);
sl = http_get_stline(htx);
/* Adjust server's health based on status code. Note: status codes 501
* and 505 are triggered on demand by client request, so we must not
* count them as server failures.
*/
if (objt_server(s->target)) {
if (sl->info.res.status >= 100 && (sl->info.res.status < 500 || sl->info.res.status == 501 || sl->info.res.status == 505))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_OK);
else
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_STS);
}
/* Perform a L7 retry because of the status code */
if ((txn->flags & TX_L7_RETRY) &&
l7_status_match(s->be, sl->info.res.status) &&
@ -1499,17 +1515,6 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.p.http.cum_req);
}
/* Adjust server's health based on status code. Note: status codes 501
* and 505 are triggered on demand by client request, so we must not
* count them as server failures.
*/
if (objt_server(s->target)) {
if (txn->status >= 100 && (txn->status < 500 || txn->status == 501 || txn->status == 505))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_OK);
else
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_STS);
}
/*
* We may be facing a 100-continue response, or any other informational
* 1xx response which is non-final, in which case this is not the right
@ -1535,8 +1540,11 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
* header content. But it is probably stronger enough for now.
*/
if (txn->status == 101 &&
(!(txn->req.flags & HTTP_MSGF_CONN_UPG) || !(txn->rsp.flags & HTTP_MSGF_CONN_UPG)))
(!(txn->req.flags & HTTP_MSGF_CONN_UPG) || !(txn->rsp.flags & HTTP_MSGF_CONN_UPG))) {
if (objt_server(s->target))
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
goto return_bad_res;
}
/*
* 2: check for cacheability.
@ -1657,11 +1665,6 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
goto return_prx_cond;
return_bad_res:
_HA_ATOMIC_INC(&s->be->be_counters.failed_resp);
if (objt_server(s->target)) {
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.failed_resp);
health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
}
if ((s->be->retry_type & PR_RE_JUNK_REQUEST) &&
(txn->flags & TX_L7_RETRY) &&
do_l7_retry(s, s->scb) == 0) {
@ -1669,6 +1672,11 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA, s, txn);
return 0;
}
_HA_ATOMIC_INC(&s->be->be_counters.failed_resp);
if (objt_server(s->target))
_HA_ATOMIC_INC(&__objt_server(s->target)->counters.failed_resp);
txn->status = 502;
stream_inc_http_fail_ctr(s);
/* fall through */