Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-all_healthy
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-all_healthy
Commits
a01b4f26
Commit
a01b4f26
authored
Aug 10, 2018
by
Nils Goroll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial version of the all_healthy director
parent
ca6076a3
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
318 additions
and
26 deletions
+318
-26
vmod_all_healthy.c
src/vmod_all_healthy.c
+167
-3
vmod_all_healthy.vcc
src/vmod_all_healthy.vcc
+81
-13
vmod_all_healthy.vtc
src/vtc/vmod_all_healthy.vtc
+70
-10
No files found.
src/vmod_all_healthy.c
View file @
a01b4f26
#include "config.h"
#include "config.h"
#include <string.h> // memset for INIT_OBJ
#include <stdlib.h> // free/calloc
#include <cache/cache.h>
#include <cache/cache.h>
#include <vcl.h>
#include "vcc_all_healthy_if.h"
#include "vcc_all_healthy_if.h"
VCL_STRING
struct
vmod_all_healthy_director
{
vmod_hello
(
VRT_CTX
)
unsigned
magic
;
#define VMOD_ALL_HEALTHY_DIRECTOR_MAGIC 0x0d8790a3
VCL_BACKEND
dir
;
VCL_BACKEND
backend
;
int
spcconsider
;
int
nconsider
;
VCL_BACKEND
*
consider
;
};
static
VCL_BACKEND
vmod_director_resolve
(
VRT_CTX
,
VCL_BACKEND
);
static
VCL_BOOL
vmod_director_healthy
(
VRT_CTX
,
VCL_BACKEND
,
VCL_TIME
*
);
static
const
struct
vdi_methods
vmod_director_methods
[
1
]
=
{
{
.
magic
=
VDI_METHODS_MAGIC
,
.
type
=
"all_healthy"
,
.
resolve
=
vmod_director_resolve
,
.
healthy
=
vmod_director_healthy
,
}
};
VCL_VOID
vmod_director__init
(
VRT_CTX
,
struct
vmod_all_healthy_director
**
dp
,
const
char
*
vcl_name
)
{
{
struct
vmod_all_healthy_director
*
d
;
const
int
spc
=
4
;
AN
(
dp
);
AZ
(
*
dp
);
ALLOC_OBJ
(
d
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
if
(
d
==
NULL
)
{
VRT_fail
(
ctx
,
"obj alloc failed"
);
return
;
}
d
->
consider
=
calloc
(
spc
,
sizeof
(
VCL_BACKEND
));
if
(
d
->
consider
==
NULL
)
{
VRT_fail
(
ctx
,
"consider list alloc failed"
);
goto
fail_consider
;
}
d
->
spcconsider
=
spc
;
d
->
dir
=
VRT_AddDirector
(
ctx
,
vmod_director_methods
,
d
,
"%s"
,
vcl_name
);
if
(
d
->
dir
==
NULL
)
{
VRT_fail
(
ctx
,
"AddDirector failed"
);
goto
fail_dir
;
}
*
dp
=
d
;
return
;
fail_dir:
free
(
TRUST_ME
(
d
->
consider
));
fail_consider:
FREE_OBJ
(
d
);
return
;
}
VCL_VOID
vmod_director__fini
(
struct
vmod_all_healthy_director
**
dp
)
{
struct
vmod_all_healthy_director
*
d
=
*
dp
;
*
dp
=
NULL
;
if
(
d
==
NULL
)
return
;
CHECK_OBJ
(
d
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
VRT_DelDirector
(
&
d
->
dir
);
free
(
TRUST_ME
(
d
->
consider
));
FREE_OBJ
(
d
);
}
#define check_init(ctx, name) do { \
if (((ctx)->method & VCL_MET_INIT) == 0) { \
VRT_fail(ctx, "." #name \
" can only be called from vcl_init {}"); \
return; \
} \
} while(0)
VCL_VOID
vmod_director_consider
(
VRT_CTX
,
struct
vmod_all_healthy_director
*
d
,
VCL_BACKEND
b
)
{
int
i
;
void
*
n
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
return
(
"vmod-all_healthy"
);
CHECK_OBJ
(
d
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
check_init
(
ctx
,
consider
);
if
(
b
==
NULL
)
{
VRT_fail
(
ctx
,
"cannot consider a NULL backend"
);
return
;
}
for
(
i
=
0
;
i
<
d
->
nconsider
;
i
++
)
{
if
(
d
->
consider
[
i
]
==
b
)
return
;
}
if
(
d
->
spcconsider
==
d
->
nconsider
)
{
i
=
d
->
spcconsider
<<
1
;
n
=
realloc
(
d
->
consider
,
i
*
sizeof
(
VCL_BACKEND
));
if
(
n
==
NULL
)
{
VRT_fail
(
ctx
,
"growing consider list failed"
);
return
;
}
d
->
spcconsider
=
i
;
d
->
consider
=
n
;
}
d
->
consider
[
d
->
nconsider
++
]
=
b
;
if
(
d
->
backend
==
NULL
)
d
->
backend
=
b
;
}
VCL_VOID
vmod_director_set_backend
(
VRT_CTX
,
struct
vmod_all_healthy_director
*
d
,
VCL_BACKEND
b
)
{
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CHECK_OBJ
(
d
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
check_init
(
ctx
,
consider
);
if
(
b
==
NULL
)
{
VRT_fail
(
ctx
,
"cannot set a NULL backend"
);
return
;
}
d
->
backend
=
b
;
}
VCL_BACKEND
vmod_director_backend
(
VRT_CTX
,
struct
vmod_all_healthy_director
*
d
)
{
CHECK_OBJ
(
d
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
(
void
)
ctx
;
return
(
d
->
dir
);
}
static
VCL_BACKEND
vmod_director_resolve
(
VRT_CTX
,
VCL_BACKEND
b
)
{
struct
vmod_all_healthy_director
*
d
;
CAST_OBJ_NOTNULL
(
d
,
b
->
priv
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
return
(
d
->
backend
);
}
static
VCL_BOOL
vmod_director_healthy
(
VRT_CTX
,
VCL_BACKEND
b
,
VCL_TIME
*
t
)
{
struct
vmod_all_healthy_director
*
d
;
int
i
;
VCL_BOOL
r
=
1
;
VCL_TIME
bt
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
CAST_OBJ_NOTNULL
(
d
,
b
->
priv
,
VMOD_ALL_HEALTHY_DIRECTOR_MAGIC
);
for
(
i
=
0
;
i
<
d
->
nconsider
;
i
++
)
{
CHECK_OBJ_NOTNULL
(
d
->
consider
[
i
],
DIRECTOR_MAGIC
);
r
&=
VRT_Healthy
(
ctx
,
d
->
consider
[
i
],
&
bt
);
if
(
t
&&
bt
>
*
t
)
*
t
=
bt
;
}
return
(
r
);
}
}
src/vmod_all_healthy.vcc
View file @
a01b4f26
...
@@ -3,26 +3,94 @@ $Module all_healthy 3 Varnish all_healthy Module
...
@@ -3,26 +3,94 @@ $Module all_healthy 3 Varnish all_healthy Module
DESCRIPTION
DESCRIPTION
===========
===========
This VCC file was generated by VCDK, it is used to for both the VMOD
The all_healthy vmod provides a varnish director tieing the health
interface and its manual using reStructuredText.
state of several other backends / health states: An all_healthy
director is only healthy if all backends to consider are healthy. It
always resolves to exactly one backend, which may or may not be part
of the set of backends considered for health state.
XXX: document vmod-all_healthy
An all_healthy director will commonly be layered below other directors
for actual load balancing.
Example
Examples and use cases:
::
import all_healthy;
* Using more than one health checks for a backend::
sub vcl_deliver {
probe probe_a { ... }
set resp.http.Hello = all_healthy.hello();
probe probe_b { ... }
}
XXX: define vmod-all_healthy interface
backend be_a {
.host = "1.2.3.4";
.probe = probe_a;
}
$Function STRING hello()
# will never actually be used, only provides the second probe
backend be_b {
.host = "1.2.3.4";
.probe = probe_b;
}
Description
sub vcl_init {
Hello world for vmod-all_healthy
new be = all_healthy.director();
# implies be.set_backend(be_a);
be.consider(be_a);
be.consider(be_b);
some_director.add_backend(be);
}
sub vcl_backend_fetch {
set bereq.backend = be.backend();
}
* Checking health on a different port::
probe oob_probe { ... }
backend be_traffic {
.host = "1.2.3.4";
# no .probe !
}
backend be_oob_probe {
.host = "1.2.3.4";
.port = "4242";
.probe = oob_probe;
}
sub vcl_init {
new be = all_healthy.director();
be.consider(be_oob_probe);
be.set_backend(be_traffic);
some_director.add_backend(be);
}
sub vcl_backend_fetch {
set bereq.backend = be.backend();
}
$Object director()
Instantiate an all_healthy director.
$Method VOID .consider(BACKEND)
Add a backend to consider for determining the health state of the
director.
This method may only be called from vcl_init {}
$Method VOID .set_backend(BACKEND)
Set the backend the director resolves to.
This method may only be called from vcl_init {}
$Method BACKEND .backend()
Return the all_healthy director instance, which will resolve to the
backend set using the .set_backend() method.
SEE ALSO
SEE ALSO
========vcl\(7),varnishd\(1)
========vcl\(7),varnishd\(1)
src/vtc/vmod_all_healthy.vtc
View file @
a01b4f26
varnishtest "test vmod-all_healthy"
varnishtest "test vmod-all_healthy"
server s1 {
varnish v1 -vcl {
rxreq
import std;
txresp
import vtc;
} -start
import all_healthy;
backend be_a { .host = "${bad_backend}"; }
backend be_b { .host = "${bad_backend}"; }
varnish v1 -vcl+backend {
sub vcl_init {
import all_healthy;
new be = all_healthy.director();
be.consider(be_a);
be.consider(be_b);
}
sub vcl_recv {
return (synth(200));
}
sub vcl_deliver {
sub vcl_synth {
set resp.http.Hello = all_healthy.hello();
set resp.http.a = std.healthy(be_a);
}
set resp.http.b = std.healthy(be_b);
set resp.http.be = std.healthy(be.backend());
set resp.http.name = be.backend();
}
} -start
} -start
varnish v1 -cliok "backend.list -j"
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.a == true
expect resp.http.b == true
expect resp.http.be == true
expect resp.http.name == be
} -run
varnish v1 -cliok "backend.set_health be_a sick"
varnish v1 -cliok "backend.list -j"
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.a == false
expect resp.http.b == true
expect resp.http.be == false
expect resp.http.name == be
} -run
varnish v1 -cliok "backend.set_health be_a healthy"
varnish v1 -cliok "backend.set_health be_b sick"
varnish v1 -cliok "backend.list -j"
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.a == true
expect resp.http.b == false
expect resp.http.be == false
expect resp.http.name == be
} -run
varnish v1 -cliok "backend.set_health be_b healthy"
varnish v1 -cliok "backend.list -j"
client c1 {
client c1 {
txreq
txreq
rxresp
rxresp
expect resp.status == 200
expect resp.status == 200
expect resp.http.Hello == "vmod-all_healthy"
expect resp.http.a == true
expect resp.http.b == true
expect resp.http.be == true
expect resp.http.name == be
} -run
} -run
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment