Boost Symfony with Varnish
Varnish is an HTTP accelerator designed for content-heavy dynamic web sites as well as heavily consumed APIs.
TYPE OF CACHES
BROWSER CACHE
CLIENT PROXY CACHE
REVERSE PROXY CACHE
HOW IT WORKS?
HOW IT WORKS?
Expiration
Cache-Control/Expires
HOW IT WORKS?
Validation
Last-Modified / If-Modified-Since ETag / If-None-Match
HTTP EXPIRATION
HTTP EXPIRATION
HTTP EXPIRATION
HTTP VALIDATION
HTTP VALIDATION
HTTP VALIDATION
VCL
VCL
VCL - Varnish configuration Language
The VCL language is a small domain-specific language designed to be used to define request handling and document caching policies for the Varnish HTTP accelerator. When a new configuration is loaded, the varnishd management process translates the VCL code to C and compiles it to a shared object which is then dynamically linked into the server process.
STATE MACHINE
STATE MACHINE
STATE MACHINE
VCL_RECV
# All unknown methods should be piped to the backend
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
std.log("Unknown method " + req.method + " is piped to the backend");
return(pipe);
}
# We only deal with GET and HEAD by default
if (req.method != "GET" && req.method != "HEAD") {
std.log("Method is " + req.method + " and passed to the backend directly");
return(pass);
}
VCL_RECV
# This block will remove every unknown cookie except the server known cookies.
# Known server cookies are: sid (early PHPSESSID), session_token
if (req.http.Cookie && !req.http.X-Cookie) {
set req.http.Cookie = ";" + req.http.Cookie;
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
set req.http.Cookie = regsuball(req.http.Cookie, ";(sid|session_token|ssid)=", "; \1=");
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
# Clean empty Cookie header
if (req.http.Cookie == "") {
unset req.http.Cookie;
}
# Save cookie to X-Cookie header
set req.http.X-Cookie = req.http.Cookie;
}
# All internal subrequests that declared stateless will be made without any cookies
if (req.url ~ "^/_internal/" && req.url ~ "stateless") {
std.log("Request to the internal stateless block, will be made without any cookies");
unset req.http.Cookie;
}
VCL_RECV
# Inform backend that we capable to process surrogates
set req.http.Surrogate-Capability = "Varnish=ESI/1.0";
# Always try to lookup, even for clients with cookies
std.log("Trying to lookup in the cache");
return(hash);
VCL_BACKEND_RESPONSE
# Instruct Varnish to keep the objects in the cache beyond their TTL
set beresp.grace = 24h;
# Copy url to internal headers for lurker-friendly bans
set beresp.http.X-Url = bereq.url;
set beresp.http.X-Host = bereq.http.host;
# Enable processing of ESI if backend has reported that it want to be processed with ESI
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
// for Varnish >= 3.0
set beresp.do_esi = true;
}
VCL_BACKEND_RESPONSE
# Cache 404s and 301s for 5 minutes to prevent a possible attack on backends
if (beresp.status == 404 || beresp.status == 301) {
std.log("Received " + beresp.status + " code from the backend. Cache it");
set beresp.ttl = 5m;
return(deliver);
}
# Do not cache anything with no-cache directive
if (beresp.http.Cache-Control ~ "no-cache") {
set beresp.uncacheable = true;
}
VCL_HIT
sub vcl_hit {
if (obj.ttl >= 0s) {
# A pure unadultered hit, deliver it
return (deliver);
}
# Graced delivery
if (obj.ttl + obj.grace > 0s) {
set req.http.X-Cache-Has-Stale = true;
return (deliver);
}
# Fetch & deliver once we get the result
return (fetch);
}
CACHE INVALIDATION
sub vcl_recv {
# Restrict access to the PURGE method by "purge" ACL
if (req.method == "PURGE") {
if (!std.ip(regsub(req.http.X-Forwarded-For, "[, ].*$", ""), client.ip) ~ purge) {
return (synth(405, "Not allowed."));
}
ban("obj.http.X-Host == " + req.http.host + "
&& obj.http.X-Url ~ " + req.http.X-Purge-Regex);
return (synth(200, "Purged. Host: " + req.http.host +
" Regex:" + req.http.X-Purge-Regex));
}
}
LIVE REFRESH
sub vcl_recv {
# Editors can reload cache by forcing page
if (req.http.Cache-Control ~ "no-cache" &&
std.ip(regsub(req.http.X-Forwarded-For, "[, ].*$", ""), client.ip) ~ editors) {
std.log("Editor from IP: " + client.ip + " requests a cache refresh");
std.log("Mark request as always miss from cache");
set req.hash_always_miss = true;
set req.http.X-Cache-Always-Miss = true;
}
}
THANKS!
Boost Symfony with Varnish
By Alexander Lisachenko
Boost Symfony with Varnish
- 677