天天看點

Varnish緩存伺服器實作網站負載均衡、動靜分離

       varnish 緩存是 web 應用加速器,同時也作為 http 反向緩存代理。你可以安裝 varnish 在任何http 的前端,同時配置它緩存内容。與傳統的 squid 相比,varnish 具有性能更高、速度更快、管理更加友善等諸多優點。

案例1  使用Varnish實作負載均衡以及頁面緩存

1 、拓撲環境

Varnish:192.168.31.250

Web01:192.168.31.10

Web02:192.168.31.20

2、安裝 varnish、web01、web02

[root@varnish ~]#  yum -y install  varnish

[root@web01 ~]#  yum -y install nginx

[root@web02 ~]#  yum -y install nginx

3、varnish 的vcl  檔案配置内容:

[root@varnish ~]#  cat  /etc/varnish/default.vcl

4、啟動Varnish

[root@varnish ~]# varnishd  -f  /etc/varnish/default.vcl        #啟動

[root@varnish ~]# pkill  varnishd                                       #關閉服務

5、用戶端通路驗證

通路varnish伺服器 http://192.168.31.250,varnish會根據算法配置設定流量

案例2  使用Varnish實作動靜分離

注意:在實作兩台後端主機負載均衡時需将此路徑設定為不緩存直接從後端主機中取得資料

varnish 的vcl  檔案配置内容:

#使用 varnish 版本 4 的格式.

vcl 4.0;

#加載後端負載均衡子產品

import directors;

#加載 std 子產品

import std;

#建立名為 backend_healthcheck 的健康檢查政策

probe backend_healthcheck {

.url="/";

.interval = 5s;

.timeout = 1s;

.window = 5;

.threshold = 3;

}

#定義後端伺服器

backend web_app_01 {

.host = "192.168.31.10";

.port = "80";

.first_byte_timeout = 9s;

.connect_timeout = 3s;

.between_bytes_timeout = 1s;

.probe = backend_healthcheck;

backend web_app_02 {

.host = "192.168.31.20";

#定義允許清理緩存的 IP

acl purgers {

"127.0.0.1";

"localhost";

"192.168.31.0/24";

#vcl_init 初始化子程式建立後端主機組

sub vcl_init {

new web = directors.round_robin();

web.add_backend(web_app_01);

web.add_backend(web_app_02);

#請求入口,用于接收和處理請求。這裡一般用作路由處理,判斷是否讀取緩存和指定該請求使用哪個後端

sub vcl_recv {

        #将.php結尾的檔案發往web_app_01,将其他結尾的檔案發往web_app_02

        if (req.url ~ "(?i)\.php$") {           

            set req.backend_hint = web_app_01; 

            } else { 

            set req.backend_hint = web_app_02;          

            }    

        #url中開頭帶有login的直接從後端主機取結果不緩存 

        if (req.url ~"(?i)^/login") {          

        return(pass); 

        }

# 比對清理緩存的請求

if (req.method == "PURGE") {

if (!client.ip ~ purgers) {

return (synth(405, "Not Allowed."));

# 是的話就執行清理

return (purge);

# 如果不是正常請求 就直接穿透沒商量

if (req.method != "GET" &&

req.method != "HEAD" &&

req.method != "PUT" &&

req.method != "POST" &&

req.method != "TRACE" &&

req.method != "OPTIONS" &&

req.method != "PATCH" &&

req.method != "DELETE") {

return (pipe);

# 如果不是 GET 和 HEAD 就跳到 pass

if (req.method != "GET" && req.method != "HEAD") {

return (pass);

#如果比對動态内容通路請求就跳到 pass

if (req.url ~ "\.(php|asp|aspx|jsp|do|ashx|shtml)($|\?)") {

#具有身份驗證的請求跳到 pass

if (req.http.Authorization) {

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)$") {

unset 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 {

"\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico|gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)

($|\?)") {

unset req.http.cookie;

return (hash);

# 把真實用戶端 IP 傳遞給後端伺服器 後端伺服器日志使用 X-Forwarded-For 來接收

if (req.restarts == 0) {

if (req.http.X-Forwarded-For) {

set req.http.X-Forwarded-For = req.http.X-Forwarded-For + ", " + client.ip;

set req.http.X-Forwarded-For = client.ip;

# hash 事件(緩存事件)

sub vcl_hash {

hash_data(req.url);

if (req.http.host) {

hash_data(req.http.host);

hash_data(server.ip);

return (lookup);

# 緩存命中事件

sub vcl_hit {

return (synth(200, "Purged."));

return (deliver);

# 緩存不命中事件

sub vcl_miss {

return (synth(404, "Purged."));

return (fetch);

# 傳回給使用者的前一個事件 通常用于添加或删除 header 頭

sub vcl_deliver {

if (obj.hits > 0) {

set resp.http.X-Cache = "HIT";

set resp.http.X-Cache-Hits = obj.hits;

set resp.http.X-Cache = "MISS";

#取消顯示 php 架構版本的 header 頭

unset resp.http.X-Powered-By;

#取消顯示 web 軟體版本、Via(來自 varnish)等 header 頭 為了安全

unset resp.http.Server;

unset resp.http.X-Drupal-Cache;

unset resp.http.Via;

unset resp.http.Link;

unset resp.http.X-Varnish;

#顯示請求經曆 restarts 事件的次數

set resp.http.xx_restarts_count = req.restarts;

#顯示該資源緩存的時間機關秒

set resp.http.xx_Age = resp.http.Age;

#顯示該資源命中的次數

set resp.http.hit_count = obj.hits;

#取消顯示 Age 為了不和 CDN 沖突

unset resp.http.Age;

#傳回給使用者

# pass 事件

sub vcl_pass {

#處理對後端傳回結果的事件(設定緩存、移除 cookie 資訊、設定 header 頭等) 在 fetch 事件後自動調用

sub vcl_backend_response {

#開啟 grace 模式 表示當後端全挂掉後 即使緩存資源已過期(超過緩存時間) 也會把該資源傳回給使用者 資源最大有效時間為 5 分鐘

set beresp.grace = 5m;

#後端傳回如下錯誤狀态碼 則不緩存

if (beresp.status == 499 || beresp.status == 404 || beresp.status == 502) {

set beresp.uncacheable = true;

#如請求 php 或 jsp 則不緩存

if (bereq.url ~ "\.(php|jsp)(\?|$)") {

} else { //自定義緩存檔案的緩存時長,即 TTL 值

if (bereq.url ~ "\.(css|js|html|htm|bmp|png|gif|jpg|jpeg|ico)($|\?)") {

set beresp.ttl = 15m;

unset beresp.http.Set-Cookie;

} elseif (bereq.url ~ "\.(gz|tgz|bz2|tbz|zip|rar|mp3|mp4|ogg|swf|flv)($|\?)") {

set beresp.ttl = 30m;

set beresp.ttl = 10m;

sub vcl_purge {

return (synth(200,"success"));

sub vcl_backend_error {

if (beresp.status == 500 ||

beresp.status == 501 ||

beresp.status == 502 ||

beresp.status == 503 ||

beresp.status == 504) {

return (retry);

sub vcl_fini {

return (ok);

繼續閱讀