forked from varnish/varnish-modules
-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
vmod_saintmode.vcc
170 lines (121 loc) · 4.59 KB
/
vmod_saintmode.vcc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
$Module saintmode 3 "Saint mode backend director"
DESCRIPTION
===========
This VMOD provides saintmode functionality for Varnish Cache 4.1 and
newer. The code is in part based on Poul-Henning Kamp's saintmode
implementation in Varnish 3.0.
Saintmode lets you deal with a backend that is failing in random ways
for specific requests. It maintains a denylist per backend, marking
the backend as sick for specific objects. When the number of objects
marked as sick for a backend reaches a set threshold, the backend is
considered sick for all requests. Each denylisted object carries a
TTL, which denotes the time it will stay denylisted.
Saintmode in Varnish 4.1 is implemented as a director VMOD. We instantiate a
saintmode object and give it a backend as an argument. The resulting object can
then be used in place of the backend, with the effect that it also has added
saintmode capabilities.
Any director will then be able to use the saintmode backends, and as
backends marked sick are skipped by the director, this provides a way
to have fine grained health status on the backends, and making sure that
retries get a different backend than the one which failed.
.. vcl-start
Example::
vcl 4.0;
import saintmode;
import directors;
backend tile1 { .host = "192.0.2.11"; .port = "80"; }
backend tile2 { .host = "192.0.2.12"; .port = "80"; }
sub vcl_init {
# Instantiate sm1, sm2 for backends tile1, tile2
# with 10 denylisted objects as the threshold for marking the
# whole backend sick.
new sm1 = saintmode.saintmode(tile1, 10);
new sm2 = saintmode.saintmode(tile2, 10);
# Add both to a director. Use sm0, sm1 in place of tile1, tile2.
# Other director types can be used in place of random.
new imagedirector = directors.random();
imagedirector.add_backend(sm1.backend(), 1);
imagedirector.add_backend(sm2.backend(), 1);
}
sub vcl_backend_fetch {
# Get a backend from the director.
# When returning a backend, the director will only return backends
# saintmode says are healthy.
set bereq.backend = imagedirector.backend();
}
sub vcl_backend_response {
if (beresp.status >= 500) {
# This marks the backend as sick for this specific
# object for the next 20s.
saintmode.denylist(20s);
# Retry the request. This will result in a different backend
# being used.
return (retry);
}
}
.. vcl-end
$ABI vrt
$Function VOID denylist(PRIV_VCL, DURATION expires)
Marks the backend as sick for a specific object. Used in vcl_backend_response.
Corresponds to the use of ``beresp.saintmode`` in Varnish 3.0. Only available
in vcl_backend_response.
Example::
sub vcl_backend_response {
if (beresp.http.broken-app) {
saintmode.denylist(20s);
return (retry);
}
}
$Function STRING status(PRIV_VCL)
Returns a JSON formatted status string suitable for use in vcl_synth.
::
sub vcl_recv {
if (req.url ~ "/saintmode-status") {
return (synth(700, "OK"));
}
}
sub vcl_synth {
if (resp.status == 700) {
synthetic(saintmode.status());
return (deliver);
}
}
Example JSON output:
::
{
"saintmode" : [
{ "name": "sm1", "backend": "foo", "count": "3", "threshold": "10" },
{ "name": "sm2", "backend": "bar", "count": "2", "threshold": "5" }
]
}
$Object saintmode(PRIV_VCL, BACKEND backend, INT threshold)
Constructs a saintmode director object. The ``threshold`` argument sets
the saintmode threshold, which is the maximum number of items that can be
denylisted before the whole backend is regarded as sick. Corresponds with the
``saintmode_threshold`` parameter of Varnish 3.0.
Example::
sub vcl_init {
new sm = saintmode.saintmode(b, 10);
}
$Method BACKEND .backend()
Used for assigning the backend from the saintmode object.
Example::
sub vcl_backend_fetch {
set bereq.backend = sm.backend();
}
$Method INT .denylist_count()
Returns the number of objects currently denylisted for a saintmode
director object.
Example:
::
sub vcl_deliver {
set resp.http.troublecount = sm.denylist_count();
}
$Method BOOL .is_healthy()
Checks if the object is currently denylisted for a saintmode director object.
If there are no valid objects available (called from vcl_hit or vcl_recv),
the function will fall back to the backend's health function.
DEPRECATED
==========
$Alias blacklist denylist
$Alias .blacklist_count saintmode.denylist_count