I am a little lost as I'm experiencing a 503
-error with Varnish, whilst using it in a docker-compose
container.
varnishlog
returns this:
varnish_1 | * << BeReq >> 3
varnish_1 | - Begin bereq 2 pass
varnish_1 | - Timestamp Start: 1503505759.849314 0.000000 0.000000
varnish_1 | - BereqMethod GET
varnish_1 | - BereqURL /
varnish_1 | - BereqProtocol HTTP/1.1
varnish_1 | - BereqHeader Host: localhost
varnish_1 | - BereqHeader Pragma: no-cache
varnish_1 | - BereqHeader Cache-Control: no-cache
varnish_1 | - BereqHeader Upgrade-Insecure-Requests: 1
varnish_1 | - BereqHeader User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
varnish_1 | - BereqHeader Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
varnish_1 | - BereqHeader Accept-Encoding: gzip, deflate, br
varnish_1 | - BereqHeader Accept-Language: de,de-DE;q=0.8,en-US;q=0.6,en;q=0.4
varnish_1 | - BereqHeader X-Forwarded-For: 172.18.0.1, 172.18.0.1
varnish_1 | - BereqHeader Via: varnish-default
varnish_1 | - BereqHeader startedAt: 1503505759.849
varnish_1 | - BereqHeader X-Varnish: 3
varnish_1 | - VCL_call BACKEND_FETCH
varnish_1 | - VCL_return fetch
varnish_1 | - FetchError no backend connection
varnish_1 | - Timestamp Beresp: 1503505759.849366 0.000052 0.000052
varnish_1 | - Timestamp Error: 1503505759.849370 0.000056 0.000004
varnish_1 | - BerespProtocol HTTP/1.1
varnish_1 | - BerespStatus 503
varnish_1 | - BerespReason Service Unavailable
varnish_1 | - BerespReason Backend fetch failed
varnish_1 | - BerespHeader Date: Wed, 23 Aug 2017 16:29:19 GMT
varnish_1 | - BerespHeader Server: Varnish
varnish_1 | - VCL_call BACKEND_ERROR
varnish_1 | - BerespHeader Content-Type: text/html; charset=utf-8
varnish_1 | - BerespHeader Retry-After: 5
varnish_1 | - VCL_return deliver
varnish_1 | - Storage malloc Transient
varnish_1 | - ObjProtocol HTTP/1.1
varnish_1 | - ObjStatus 503
varnish_1 | - ObjReason Backend fetch failed
varnish_1 | - ObjHeader Date: Wed, 23 Aug 2017 16:29:19 GMT
varnish_1 | - ObjHeader Server: Varnish
varnish_1 | - ObjHeader Content-Type: text/html; charset=utf-8
varnish_1 | - ObjHeader Retry-After: 5
varnish_1 | - Length 278
varnish_1 | - BereqAcct 0 0 0 0 0 0
varnish_1 | - End
This is my default.vcl
's content:
# varnish version 4
vcl 4.0;
import std;
import directors;
# backend start
backend default {
.host = "web";
.port = "80";
.connect_timeout = 30s;
.first_byte_timeout = 600s;
.between_bytes_timeout = 1s;
.probe = {
.url = "/robots.txt";
.interval = 10s;
.timeout = 5s;
.window = 5;
.threshold = 3;
}
}
# backend end
#############
# Housekeeping
# init start
sub vcl_init {
new magento2 = directors.fallback();
magento2.add_backend(default);
}
# init end
sub vcl_fini {
return (ok);
}
#############
# Client side
acl purge {
"web";
"php";
"localhost";
}
sub vcl_recv {
call custom_ctrl;
if (req.method == "PURGE") {
if (client.ip !~ purge) {
return (synth(405, "Method not allowed"));
}
if (!req.http.X-Magento-Tags-Pattern) {
return (synth(400, "X-Magento-Tags-Pattern header required"));
}
ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern);
return (synth(200, "Purged"));
}
/* We do not support SPDY or HTTP/2.0 */
if (req.method == "PRI") {
return (synth(405));
}
if (req.restarts == 0) {
/* set X-Forwarded-For */
if (req.http.X-Forwarded-For) {
set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;
} else {
set req.http.X-Forwarded-For = client.ip;
}
/* set Via */
if (req.http.Via) {
set req.http.Via = req.http.Via + ", varnish-default";
} else {
set req.http.Via = "varnish-default";
}
set req.http.startedAt = std.time2real(now, 0.0);
}
/* backend selector */
if (req.url ~ "^/max") {
set req.backend_hint = magento2.backend();
}
if (req.method != "GET" &&
req.method != "HEAD" &&
req.method != "PUT" &&
req.method != "POST" &&
req.method != "TRACE" &&
req.method != "OPTIONS" &&
req.method != "DELETE") {
/* Non-RFC2616 or CONNECT which is weird. */
return (pipe);
}
/* Implementing websocket support (https://www.varnish-cache.org/docs/4.0/users-guide/vcl-example-websockets.html) */
if (req.http.Upgrade ~ "(?i)websocket") {
return (pipe);
}
if (req.method != "GET" && req.method != "HEAD") {
/* We only deal with GET and HEAD by default */
return (pass);
}
/* Not cacheable */
if (req.http.Authorization) {
return (pass);
}
# no cache request
if (req.http.Cache-Control == "no-cache" || req.url ~ "cache-control=no-cache") {
return (pass);
}
# Send Surrogate-Capability headers to announce ESI support to backend
# set req.http.Surrogate-Capability = "key=ESI/1.0";
# sort the query string
set req.url = std.querysort(req.url);
# Bypass shopping cart, checkout and search requests
if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") {
return (pass);
}
# normalize url in case of leading HTTP scheme and domain
set req.url = regsub(req.url, "^http[s]?://", "");
# Cookies
std.collect(req.http.Cookie);
# Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") {
# No point in compressing these
unset req.http.Accept-Encoding;
} elsif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") {
set req.http.Accept-Encoding = "deflate";
} else {
# unkown algorithm
unset req.http.Accept-Encoding;
}
}
# Remove Google gclid parameters to minimize the cache objects
set req.url = regsuball(req.url,"\?gclid=[^&]+$",""); # strips when QS = "?gclid=AAA"
set req.url = regsuball(req.url,"\?gclid=[^&]+&","?"); # strips when QS = "?gclid=AAA&foo=bar"
set req.url = regsuball(req.url,"&gclid=[^&]+",""); # strips when QS = "?foo=bar&gclid=AAA" or QS = "?foo=bar&gclid=AAA&bar=baz"
# static files are always cacheable. remove SSL flag and cookie
if (req.url ~ "^/(pub/)?(media|static)/.*\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)$") {
unset req.http.Https;
unset req.http.X-Forwarded-Proto;
unset req.http.Cookie;
}
return (hash);
}
sub vcl_pipe {
# By default Connection: close is set on all piped requests, to stop
# connection reuse from sending future requests directly to the
# (potentially) wrong backend. If you do want this to happen, you can undo
# it here.
# unset bereq.http.connection;
if (req.http.upgrade) {
set bereq.http.upgrade = req.http.upgrade;
}
return (pipe);
}
sub vcl_pass {
return (fetch);
}
sub vcl_hash {
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
if (req.http.cookie ~ "X-Magento-Vary=") {
hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}
# For multi site configurations to not cache each other's content
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
# To make sure http users don't see ssl warning
if (req.http.X-Forwarded-Proto) {
hash_data(req.http.X-Forwarded-Proto);
}
return (lookup);
}
sub vcl_purge {
return (synth(200, "Purged"));
}
sub vcl_hit {
if (obj.ttl > 0s) {
# A pure unadultered hit, deliver it
return (deliver);
}
# backend is healthy
if (std.healthy(req.backend_hint)) {
# set the stale
if(obj.ttl + std.duration(std.integer(regsub(obj.http.Cache-Control, "[\s\S]*m-stale=(\d)+[\s\S]*", "\1"), 2) + "s", 2s) > 0s){
return (deliver);
}
} else if (obj.ttl + obj.grace > 0s) {
# Object is in grace, deliver it
# Automatically triggers a background fetch
return (deliver);
}
# fetch & deliver once we get the result
return (miss);
}
sub vcl_miss {
return (fetch);
}
sub vcl_deliver {
# Happens when we have all the pieces we need, and are about to send the
# response to the client.
#
# You can do accounting or modifying the final object here.
set resp.http.X-Hits = obj.hits;
set req.http.varnishUse = now - std.real2time(std.real(req.http.startedAt, 0.0), now);
if (resp.http.Server-Timing) {
if (std.real(req.http.varnishUse, 0) > 0) {
set resp.http.Server-Timing = "9=" + req.http.varnishUse + ";Varnish," + resp.http.Server-Timing;
} else {
set resp.http.Server-Timing = "9=0.000;Varnish," + resp.http.Server-Timing;
}
} else {
if (std.real(req.http.varnishUse, 0) > 0) {
set resp.http.Server-Timing = "9=" + req.http.varnishUse + ";Varnish";
} else {
set resp.http.Server-Timing = "9=0.000;Varnish";
}
}
return (deliver);
}
# custom control
sub custom_ctrl{
#响应healthy检测
if(req.url == "/ping"){
return(synth(701));
}
if(req.url == "/varnish/version") {
return(synth(702));
}
}
sub vcl_synth {
if (resp.status == 701) {
synthetic("pong");
} elsif (resp.status == 702) {
synthetic("2017-08-20T16:27:55.780Z");
}
set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
set resp.status = 200;
set resp.http.Content-Type = "text/plain; charset=utf-8";
return (deliver);
}
###############
# Backend Fetch
sub vcl_backend_fetch {
return (fetch);
}
sub vcl_backend_response {
if (bereq.uncacheable) {
return (deliver);
}
if (beresp.http.content-type ~ "text") {
set beresp.do_esi = true;
}
# cache only successfully responses and 404s
if (beresp.status != 200 && beresp.status != 404) {
set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);
} elsif (beresp.http.Cache-Control ~ "private") {
set beresp.uncacheable = true;
set beresp.ttl = 86400s;
return (deliver);
}
if (beresp.http.X-Magento-Debug) {
set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control;
}
# validate if we need to cache it and prevent from setting cookie
# images, css and js are cacheable by default so we have to remove cookie also
if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) {
unset beresp.http.set-cookie;
if (bereq.url !~ "\.(ico|css|js|jpg|jpeg|png|gif|tiff|bmp|gz|tgz|bz2|tbz|mp3|ogg|svg|swf|woff|woff2|eot|ttf|otf)(\?|$)") {
set beresp.http.Pragma = "no-cache";
set beresp.http.Expires = "-1";
set beresp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0";
set beresp.grace = 1m;
}
}
# the response body is text, do gzip (judge by response header Content-Type)
if (beresp.http.Content-Type ~ "text" || beresp.http.Content-Type ~ "application/javascript" || beresp.http.Content-Type ~ "application/json") {
set beresp.do_gzip = true;
}
# The following scenarios set uncacheable
if (beresp.ttl <= 0s ||
beresp.http.Set-Cookie ||
beresp.http.Surrogate-Control ~ "no-store" ||
(!beresp.http.Surrogate-Control &&
beresp.http.Cache-Control ~ "no-cache|no-store|private") ||
beresp.http.Vary == "*"){
# Hit-For-Pass
set beresp.uncacheable = true;
set beresp.ttl = 300s;
set beresp.grace = 0s;
return (deliver);
}
# Pause ESI request and remove Surrogate-Control header
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
unset beresp.http.Surrogate-Control;
set beresp.do_esi = true;
}
return (deliver);
}
You might wonder why there is .host = "web"
in the config - this is due to the fact that docker-compose magically creates configs for each node in the docker-compose.yml
file for linked services, which is in my case web
as the servicename for the nginx instance.
I'm able to ping web
from the varnish
container, so the linking is okay. Also, this is the preferred and purposed usage of docker containers.
nginx is listening on Port 80 (like varnish, internally). I tried nginx on 8080 before, but it kept somehow listening to tcp:80 and there were no error output, so I gave it a try to map both services on port 80 and it seems to work fine; however, the problem exists if I switch nginx to port 8080. Keep in mind that nginx is always listening to port 80 if you use FROM nginx
in your Dockerfile for the web
-container, so this also might not be the problem.
Happy to provide more information.
答案 0 :(得分:0)
这个Github-Issue中的答案为我解决了这个问题。因为看起来调查会产生问题。我不知道为什么,但使用问题本身标记的较小的配置文件正在工作。