2、后端WEB服务健康检测
# vim /usr/local/varnish/etc/health_check.vcl
probe backend_healthcheck {
.interval = 5s;
.timeout = 3s;
.window = 10;
.threshold = 8;
.request =
"GET /index.html HTTP/1.1"
"Host: mycheckweb.mytest.com"
"Connection: close"
"Accept-Encoding: foo/bar";
}
-----------------------------------------------------------------------------------------------------------------------------------------------
3、后端WEB服务定义
# vim /usr/local/varnish/etc/hosts/10.160.22.88_8080.conf
backend WEBSRV_10_160_22_88_8080 {
.host = "10.160.22.88";
.port = "8080";
.connect_timeout = 50s;
.between_bytes_timeout = 30s;
.first_byte_timeout = 30s;
.probe = backend_healthcheck;
}
# vim /usr/local/varnish/etc/hosts/10.173.146.35_8080.conf
backend WEBSRV_10_173_146_35_8080 {
.host = "10.173.146.35";
.port = "8080";
.connect_timeout = 50s;
.between_bytes_timeout = 30s;
.first_byte_timeout = 30s;
.probe = backend_healthcheck;
}
-----------------------------------------------------------------------------------------------------------------------------------------------
4、集群定义
# vim /usr/local/varnish/etc/cluster.vcl
include "/usr/local/varnish/etc/health_check.vcl";
include "/usr/local/varnish/etc/hosts/10.160.22.88_8080.conf";
include "/usr/local/varnish/etc/hosts/10.173.146.35_8080.conf";
director CLUSTER_BACKEND_SERVER round-robin {
{ .backend = WEBSRV_10_160_22_88_8080; }
{ .backend = WEBSRV_10_173_146_35_8080; }
}
-----------------------------------------------------------------------------------------------------------------------------------------------
5、Varnish主配置文件
# vim /usr/local/varnish/etc/varnish.vcl
include "/usr/local/varnish/etc/cluster.vcl";
acl allow_purge_cache {
"127.0.0.1";
"10.0.0.0"/8;
"172.0.0.0"/8;
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ allow_purge_cache) {
error 405 "Not Allowed.";
}
return (lookup);
}
if (req.http.host ~ "^(.*).mytest.com") {
set req.backend = CLUSTER_BACKEND_SERVER;
}
## 动态资源直接抛到后端服务器
if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
return (pass);
}
## 静态资源需要去除cookie信息
if (req.request == "GET" && req.url ~ "\.(css|js|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
unset req.http.cookie;
return (lookup);
}
if (req.restarts == 0) {
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;
}
}
if (req.http.Cache-Control ~ "no-cache") {
return (pass);
}
if (req.request != "GET" &&
req.request != "HEAD" &&
req.request != "PUT" &&
req.request != "POST" &&
req.request != "TRACE" &&
req.request != "OPTIONS" &&
req.request != "DELETE") {
return (pipe);
}
if (req.request != "GET" && req.request != "HEAD") {
return (pass);
}
if (req.http.Authorization || req.http.Cookie) {
return (pass);
}
## 静态资源压缩
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)$") {
remove req.http.Accept-Encoding;
} elseif (req.http.Accept-Encoding ~ "gzip") {
set req.http.Accept-Encoding = "gzip";
} elseif (req.http.Accept-Encoding ~ "deflate") {
set req.http.Accept-Encoding = "deflate";
} else {
remove req.http.Accept-Encoding;
}
}
## 防盗链设置
if (req.http.referer ~ "http://.*") {
if (!(req.http.referer ~ "http://.*\.qq\.com" ||
req.http.referer ~ "http://.*\.baidu\.com" ||
req.http.referer ~ "http://.*\.google\.com.*" ||
req.http.referer ~ "http://.*\.sogou\.com" ||
req.http.referer ~ "http://.*\.soso\.com" ||
req.http.referer ~ "http://.*\.so\.com")) {
set req.http.host = "www.mytest.com";
set req.url = "/";
}
}
if (!req.backend.healthy) {
unset req.http.Cookie;
}
## 跳过缓存大文件
if (req.http.x-pipe && req.restarts > 0) {
unset req.http.x-pipe;
return (pipe);
}
## 若backend是健康的,则仅grace 5s,如果backend不健康,则grace 1m,主要用于提高并发时的吞吐率
if (req.backend.healthy) {
set req.grace = 5s;
} else {
set req.grace = 1m;
}
}
sub vcl_pipe {
return (pipe);
}
sub vcl_pass {
if (req.request == "PURGE") {
error 502 "PURGE on a passed object";
}
}
sub vcl_hash {
hash_data(req.url);
if (req.http.host) {
hash_data(req.http.host);
} else {
hash_data(server.ip);
}
if (req.http.Accept-Encoding ~ "gzip") {
hash_data("gzip");
} elseif (req.http.Accept-Encoding ~ "deflate") {
hash_data("deflate");
}
return (hash);
}
sub vcl_hit {
if (req.request == "PURGE") {
purge;
error 200 "Purged.";
}
}
sub vcl_miss {
if (req.request == "PURGE") {
purge;
error 404 "Purged.";
}
}
sub vcl_fetch {
## 确保所有Cache中的内容在TTL过期后5分钟内不被删除,以应对高并发的场合
set beresp.grace = 5m;
if (beresp.http.Set-Cookie) {
return (hit_for_pass);
}
## 如果返回头有Cache-Control,则删除Set-Cookie头
if (beresp.http.Cache-Control && beresp.ttl > 0s) {
set beresp.grace = 1m;
unset beresp.http.Set-Cookie;
}
## 不缓存大于10MB的资源文件
if (beresp.http.Content-Length ~ "[0-9]{8,}") {
set req.http.x-pipe = "1";
return (restart);
}
if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {
return (hit_for_pass);
}
if (req.request == "GET" && req.url ~ "\.(css|js|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
unset beresp.http.set-cookie;
}
## 如果返回头没有Cache-Control,则标记为hit_for_pass,强制后续请求回源
if ((!beresp.http.Cache-Control && !beresp.http.Expires) ||
beresp.http.Pragma ~ "no-cache" ||
beresp.http.Cache-Control ~ "(no-cache|no-store|private)") {
set beresp.ttl = 120s;
return (hit_for_pass);
}
if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Vary == "*") {
set beresp.ttl = 120s;
return (hit_for_pass);
}
## 对不同类型静态资源进行缓存时间设置
if (req.request == "GET" && req.url ~ "\.(css|js|bmp|png|gif|jpg|jpeg|ico)($|\?)") {
set beresp.ttl = 15m;
} elseif (req.request == "GET" && req.url ~ "\.(gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {
set beresp.ttl = 30m;
} else {
set beresp.ttl = 10m;
}
return (deliver);
}
sub vcl_deliver {
if (obj.hits > 0) {
set resp.http.X-Cache = "HIT from " + req.http.host;
set resp.http.X-Cache-Hits = obj.hits;
} else {
set resp.http.X-Cache = "MISS from " + req.http.host;
}
## 去掉不必要的头信息
unset resp.http.X-Powered-By;
unset resp.http.Server;
unset resp.http.Via;
unset resp.http.X-Varnish;
unset resp.http.Age;
}
sub vcl_error {
if (obj.status == 503 && req.restarts < 5) {
set obj.http.X-Restarts = req.restarts;
return (restart);
}
}
sub vcl_init {
return (ok);
}
sub vcl_fini {
return (ok);
}
-----------------------------------------------------------------------------------------------------------------------------------------------
6、Varnish启动参数配置文件
# vim /usr/local/varnish/etc/varnish.conf
# Configuration file for varnish
#
# /etc/init.d/varnishd expects the variable $DAEMON_OPTS to be set from this
# shell script fragment.
#
# Maximum number of open files (for ulimit -n)
NFILES=131072
# Locked shared memory (for ulimit -l)
# Default log size is 82MB + header
MEMLOCK=82000
# Maximum number of threads (for ulimit -u)
NPROCS="unlimited"
# Set this to 1 to make init script reload try to switch vcl without restart.
# To make this work, you need to set the following variables
# explicit: VARNISH_VCL_CONF, VARNISH_ADMIN_LISTEN_ADDRESS,
# VARNISH_ADMIN_LISTEN_PORT, VARNISH_SECRET_FILE, or in short,
# use Alternative 3, Advanced configuration, below
RELOAD_VCL=1
#
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/usr/local/varnish/etc/varnish.vcl
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
VARNISH_LISTEN_ADDRESS=0.0.0.0
VARNISH_LISTEN_PORT=80
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=8080
#
# # Shared secret file for admin interface
#VARNISH_SECRET_FILE=/etc/varnish/secret
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=10
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=5000
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120
#
# # Cache file location
VARNISH_STORAGE_FILE=/data/varnish/varnish_storage.bin
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=3G
#
# # Backend storage specification
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
VARNISH_STORAGE="malloc,${VARNISH_STORAGE_SIZE}"
#
# # Default TTL used when the backend does not specify one
VARNISH_TTL=120
#
# # Other optimization parameter
HTTP_RESP_HDR_LEN="http_resp_hdr_len=8192"
HTTP_MAX_HDR="http_max_hdr=256"
HTTP_REQ_HDR_LEN="http_req_hdr_len=8192"
THREAD_POOLS="thread_pools=8"
THREAD_POOL_MIN="thread_pool_min=50"
THREAD_POOL_MAX="thread_pool_max=5120"
THREAD_POOL_TIMEOUT="thread_pool_timeout=10"
LRU_INTERVAL="lru_interval=20"
LISTEN_DEPTH="listen_depth=1024"
#
# # DAEMON_OPTS is used by the init script. If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
-f ${VARNISH_VCL_CONF} \
-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
-t ${VARNISH_TTL} \
-w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
-u nobody -g nogroup \
-s ${VARNISH_STORAGE} \
-p ${HTTP_RESP_HDR_LEN} \
-p ${HTTP_MAX_HDR} \
-p ${HTTP_REQ_HDR_LEN} \
-p ${THREAD_POOLS} \
-p ${THREAD_POOL_MIN} \
-p ${THREAD_POOL_MAX} \
-p ${THREAD_POOL_TIMEOUT} \
-p ${LRU_INTERVAL} \
-p ${LISTEN_DEPTH}"