[master] fe5e82650 When connecting to backends, respect the administrative health

Nils Goroll nils.goroll at uplex.de
Tue Apr 28 16:52:08 UTC 2020


commit fe5e82650788c1ce3dfbd29c8eeacf2b78c04ff4
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Tue Apr 28 18:06:38 2020 +0200

    When connecting to backends, respect the administrative health
    
    When making a connection a "real" backend (VBE), we checked the probed
    health state and did not take into account the administrative health
    state as set with `varnishadm backend.set_health ... {healthy,sick}`.
    
    Our documentation was not particularly explicit on this aspect either,
    but the administrative states `sick` and `healthy` made no sense if
    `auto` semantics was implied always. Also, the semantics were implicitly
    documented for `backend.list`.
    
    Implementation note:
    
    The relevant change is to call `VRT_Healthy()`, which does check the
    administrative health, in place of checking `(struct backend *)->sick`
    in `vbe_dir_getfd()`.
    
    As a `VRT_CTX` is required by `VRT_Healthy()`, we change the arguments of
    `vbe_dir_getfd()` accordingly: The busyobj can now be taken from the ctx,
    but the worker argument differs for pipe mode vs. fetch, so we preserve
    it as an explicit argument.
    
    A test for overriding a probed backend as healthy has been added to
    c00048.vtc, which requires a second probe to hit server s1 and fail.
    This is timing sensitive, so I hope that the backend probe interval
    of 5 seconds is long enough for all our test environments. If not,
    we probably need to make it longer or add another vtc.
    
    Fixes #3299

diff --git a/bin/varnishd/cache/cache_backend.c b/bin/varnishd/cache/cache_backend.c
index 9cecd54a3..5c1f5b58d 100644
--- a/bin/varnishd/cache/cache_backend.c
+++ b/bin/varnishd/cache/cache_backend.c
@@ -110,12 +110,15 @@ VBE_Connect_Error(struct VSC_vbe *vsc, int err)
 
 /*--------------------------------------------------------------------
  * Get a connection to the backend
+ *
+ * note: wrk is a separate argument because it differs for pipe vs. fetch
  */
 
 static struct pfd *
-vbe_dir_getfd(struct worker *wrk, struct backend *bp, struct busyobj *bo,
+vbe_dir_getfd(VRT_CTX, struct worker *wrk, struct backend *bp,
     unsigned force_fresh)
 {
+	struct busyobj *bo;
 	struct pfd *pfd;
 	int *fdp, err;
 	vtim_dur tmod;
@@ -123,11 +126,12 @@ vbe_dir_getfd(struct worker *wrk, struct backend *bp, struct busyobj *bo,
 	char pbuf1[VTCP_PORTBUFSIZE], pbuf2[VTCP_PORTBUFSIZE];
 
 	CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
-	CHECK_OBJ_NOTNULL(bo, BUSYOBJ_MAGIC);
+	CHECK_OBJ_NOTNULL(ctx->bo, BUSYOBJ_MAGIC);
+	bo = ctx->bo;
 	CHECK_OBJ_NOTNULL(bp, BACKEND_MAGIC);
 	AN(bp->vsc);
 
-	if (bp->sick) {
+	if (! VRT_Healthy(ctx, bp->director, NULL)) {
 		VSLb(bo->vsl, SLT_FetchError,
 		     "backend %s: unhealthy", VRT_BACKEND_string(bp->director));
 		bp->vsc->unhealthy++;
@@ -280,7 +284,7 @@ vbe_dir_gethdrs(VRT_CTX, VCL_BACKEND d)
 		http_PrintfHeader(bo->bereq, "Host: %s", bp->hosthdr);
 
 	do {
-		pfd = vbe_dir_getfd(wrk, bp, bo, extrachance == 0 ? 1 : 0);
+		pfd = vbe_dir_getfd(ctx, wrk, bp, extrachance == 0 ? 1 : 0);
 		if (pfd == NULL)
 			return (-1);
 		AN(bo->htc);
@@ -365,7 +369,7 @@ vbe_dir_http1pipe(VRT_CTX, VCL_BACKEND d)
 
 	ctx->req->res_mode = RES_PIPE;
 
-	pfd = vbe_dir_getfd(ctx->req->wrk, bp, ctx->bo, 0);
+	pfd = vbe_dir_getfd(ctx, ctx->req->wrk, bp, 0);
 
 	if (pfd == NULL) {
 		retval = SC_TX_ERROR;
diff --git a/bin/varnishtest/tests/c00048.vtc b/bin/varnishtest/tests/c00048.vtc
index 161c0d502..a5739503b 100644
--- a/bin/varnishtest/tests/c00048.vtc
+++ b/bin/varnishtest/tests/c00048.vtc
@@ -1,6 +1,27 @@
 varnishtest "Forcing health of backends"
 
-server s1 -repeat 3 {
+barrier b1 cond 2
+
+server s1 {
+	# probe
+	rxreq
+	txresp
+
+	# req
+	accept
+	rxreq
+	txresp
+	rxreq
+	txresp -hdr "Connection: close"
+
+	# probe sick
+	accept
+	rxreq
+	txresp -status 500
+	barrier b1 sync
+
+	accept
+	# req
 	rxreq
 	txresp
 } -start
@@ -13,7 +34,7 @@ varnish v1 -vcl {
 			.window = 8;
 			.initial = 7;
 			.threshold = 8;
-			.interval = 10s;
+			.interval = 5s;
 		}
 	}
 
@@ -60,6 +81,18 @@ client c1 {
 	expect resp.status == 200
 } -run
 
+# wait for sick probe
+barrier b1 sync
+
+# healthy overrides probe
+varnish v1 -cliok "backend.list"
+
+client c1 {
+	txreq
+	rxresp
+	expect resp.status == 200
+} -run
+
 varnish v1 -vsl_catchup
 
 varnish v1 -clierr 106 "backend.set_health s1 foo"
diff --git a/include/tbl/cli_cmds.h b/include/tbl/cli_cmds.h
index 84b600f80..3e737c641 100644
--- a/include/tbl/cli_cmds.h
+++ b/include/tbl/cli_cmds.h
@@ -312,8 +312,11 @@ CLI_CMD(BACKEND_LIST,
 CLI_CMD(BACKEND_SET_HEALTH,
 	"backend.set_health",
 	"backend.set_health <backend_pattern> [auto|healthy|sick]",
-	"Set health status on the backends.",
-	"",
+	"Set health status of backend(s) matching <backend_pattern>.",
+	"  * With ``auto``, the health status is determined by a probe\n"
+	"    or some other dynamic mechanism, if any\n"
+	"  * ``healthy`` sets the backend as usable\n"
+	"  * ``sick`` sets the backend as unsable\n",
 	2, 2
 )
 


More information about the varnish-commit mailing list