架構的高可用高性能keepalived和varnish

1、簡述HA cluster原理
2、keepalived實現主從、主主架構
3、簡述http協議緩存原理及常用首部講解
4、簡述回源原理和CDN常見多級緩存
5、varnish實現緩存對象及反代後端主機

1、簡述HA cluster原理

高可用集羣(High Availability Cluster)簡單的理解就是多個節點作爲一個整體向用戶提供一組網絡資源。如果某個節點失效,它的備用節點將在幾秒鐘的時間內接管它的職責。用戶將完全感受不到這個過程,因此,對於用戶而言,集羣永遠不會停機。高可用集羣軟件的主要作用就是實現故障檢查和業務切換的自動化。只有兩個節點的高可用集羣又稱爲雙機熱備,即使用兩臺服務器互相備份。

2、keepalived實現主從、主主架構

首先需要同步時間,時間不同步的話就很可能會出錯
然後下載keepalived安裝包,默認在base的yum裏面
安裝完後我們編輯配置文件/etc/keepalived.conf

! Configuration File for keepalived

global_defs {
   notification_email {
        root@localhost  #接收信息的郵件地址
   }
   notification_email_from keepalive@localhost   #郵件來自於誰,可以不存在
   smtp_server 127.0.0.1 #郵件服務器可以是自己;
   smtp_connect_timeout 30 #郵件服務器鏈接超時時長
   router_id rt1  #router標識一個組內不同的router
   vrrp_mcast_group4 224.0.0.1  #組播地址
}

vrrp_instance VI_1 {  #組名VI_1
    state MASTER 
    interface ens33   
    virtual_router_id 51   #整個虛擬組的id,同組配置須保持一致
    priority 100
    advert_int 1 #一秒檢查一次
    authentication {
        auth_type PASS #simple認證
        auth_pass 12345678  #最大支持8位
    }
    virtual_ipaddress {
        #<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE>
        192.168.31.240/24 dev ens33 label ens33:0
    }
}                    

然後將配置文件傳給另一臺主機
scp keepalived.conf [email protected]:/etc/keepalived/
在這一臺主機裏我們只需要簡單的修改幾項
router_id rt2
state BACKUP
ppriority 95 #低一點

配置到這裏就結束了,很簡單。接下來我們就可以開始測試了
先在backup機上開啓keepalive進程


13920922-9abcb1bc342fbba0.png

可以看到已經拿到地址了
現在我們在master上開啓進程


13920922-5badf5bdac286361.png
image.png

發現被更高的優先級搶走了
然後我們可以抓包查看他們互相通告的信息
13920922-f6dea55870ff0940.png
image.png

雙主模式

但如果這樣配置的話就只有一臺在工作,另一臺一直是備用的,我們可以在主機上分別配置兩個虛擬路由器,假如A,B兩臺主機我們想要讓他們同時工作起來,可以讓A爲第一個虛擬路由器的master,則B就是第二個虛擬路由器的master然後我們就有了兩個VIP,但是有了兩個VIP其他主機怎麼與我們通信實現負載均衡呢,這個時候我們就需要一個新的調度器,但我們配置keepalive本來就是爲了增強調度器的冗餘安全性,如果引入了新的節點豈不是本末倒置。
這時我們可以使用DNS服務,DNS本來就是主從互備不存在單點性且只需要我們在一個域名裏添加兩條A記錄就可以達到輪詢負載均衡的目的。
編輯配置文件增加一個虛擬路由器配置:

#RT1上添加一段
vrrp_instance VI_2 {
    state BACKUP
    interface ens33 
    virtual_router_id 52
    priority 96
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 98765432
    }
    virtual_ipaddress {
        192.168.31.241/24 dev ens33 label ens33:1                                           
    }

#RT2上添加一段
vrrp_instance VI_1 {
    state MASTER 
    interface ens33 
    virtual_router_id 52
    priority 100 
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 98765432
    }
    virtual_ipaddress {
        192.168.31.241/24 dev ens33 label ens33:1                                           
    }
}

然後我們抓包看


13920922-d72c2a23c856b283.png
image.png

每一臺主機都分別獲取到了一個IP地址如果我們down了其中一臺主機,則ip地址會跑到另一臺上,測試一下看看


13920922-8013193c8c4eb469.png
image.png

則簡單的實驗就完成了
我們可以定義發生變化時執行指定的腳本
通知腳本的使用方式:
示例通知腳本:
#!/bin/bash
#
contact='root@localhost'

notify() {
        local mailsubject="$(hostname) to be $1, vip floating"
        local mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
        echo "$mailbody" | mail -s "$mailsubject" $contact
}
case $1 in
        master)
            notify master
            ;;
        backup)
            notify backup
            ;;
        fault)
            notify fault
            ;;
        *)
                        echo "Usage: $(basename $0) {master|backup|fault}"
            exit 1
            ;;
esac        
#腳本的調用方法,寫在虛擬路由器中
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"  

3、簡述http協議緩存原理及常用首部講解

(1)強制緩存機制(過期時間機制)

基本原理:
客戶端第一次請求服務端時,服務端把緩存規則信息添加到header中,客戶端通過這些信息判斷是否能緩存。若能強制緩存,則header中會有兩個字段來標記緩存失效的時間(expires或cache-control)。在客戶端第一次請求並添加緩存後,以後每次客戶端的請求響應數據都是緩存服務器提供的,不會再是服務端。緩存服務器根據cache-control字段來判斷是否使用、是否更新、何時更新緩存。

  • expires,緩存過期時間
  • cache-control有下面幾個參數:
  • public,允許客戶端和代理使用緩存,即客戶端請求的資源可以被任何緩存區所緩存
  • private,允許客戶端使用緩存,即對於某個用戶的響應信息不能被共享緩存區所緩存
  • max-age,緩存最大失效時長(單位爲秒)
  • no-cache,關閉強制緩存,需要使用對比緩存
  • no-store,所有內容都不緩存

(2)對比緩存機制(條件式緩存機制):

基本原理:

  • a)緩存命中的情況:客戶端向緩存服務器請求獲取緩存header標識,客戶端獲取標識後,向後端服務器發送header標識規則,若未失效便通知客戶端使用緩存服務器緩存的數據(狀態碼304)。
  • b)緩存未命中的情況:客戶端向緩存服務器請求獲取緩存header標識,客戶端獲取標識後,向後端服務器發送header標識規則,若失效便通知客戶端不使用緩存服務器緩存的數據(狀態碼200),並更新緩存。
    對比緩存標識:
    last-modified/if-modfied-since:資源最後的修改時間戳
    etag/if-none-match:資源校驗碼

4、簡述回源原理和CDN常見多級緩存

回源是指瀏覽器在發送請求報文時,響應該請求報文的是源站點的服務器,而不是各節點上的緩存服務器,那麼這個過程相對於通過各節點上的緩存服務器來響應的話就稱作爲回源。回源的請求或流量太多的話,有可能會讓源站點的服務器承載着過大的訪問壓力,進而影響服務的正常訪問。
CDN(Content Delivery Network)內容分發網絡,其思路是儘可能避開網絡上的瓶頸,通過在網絡邊緣部署邊緣服務器,依靠CDN中心平臺的負載均衡、內容分發及調度等功能,使用戶就近獲取所需的內容,降低網絡擁堵,提高用戶訪問響應速度和命中率。所以基本上CDN就是廣泛採用各種緩存服務器,使得用戶的請求直接由這些緩存服務器響應,加快了響應速度;只有在用戶請求的資源在緩存服務器上沒有找到或者請求訪問的資源在源站點服務器上已經修改過的情況下,緩存服務器纔會去訪問源站點服務器以獲取最新的資源。簡單的來說就是在多個地方設置緩存服務器,使當地的用戶可直接訪問當地的緩存服務器而不必頻繁的去訪問源站,減少根服務器的壓力。


13920922-1b86fe23e0f1d047.png
image.png

CDN節點的緩存機制也是遵循http協議,因此也會受到Cache-Control等字段的影響。如果緩存的時間太短就會頻繁的向根源服務器發起請求,增加源站點的負擔,如果緩存時間太長又有可能涉及到更新的問題,這就需要設計者根據實際情況去設計。

5、varnish實現緩存對象及反代後端主機

緩存原理

Varnish 與一般服務器軟件類似,分爲 master 進程和 child 進程。Master 進程讀入存儲配置文件,調用合適的存儲類型,然後創建 / 讀入相應大小的緩存文件,接着 master 初始化管理該存儲空間的結構體,然後 fork 並監控 child 進程。Child 進程在主線程的初始化的過程中,將前面打開的存儲文件整個 mmap 到內存中,此時創建並初始化空閒結構體,掛到存儲管理結構體,以待分配。Child 進程分配若干線程進行工作,主要包括一些管理線程和很多 worker 線程。
接着,開始真正的工作,varnish 的某個負責接收新 HTTP 連接線程開始等待用戶,如果有新的 HTTP 連接過來,它總負責接收,然後喚醒某個等待中的線程,並把具體的處理過程交給它。Worker 線程讀入 HTTP 請求的 URI,查找已有的 object,如果命中則直接返回並回複用戶。如果沒有命中,則需要將所請求的內容,從後端服務器中取過來,存到緩存中,然後再回復。

分配緩存的過程是這樣的:它根據所讀到 object 的大小,創建相應大小的緩存文件。爲了讀寫方便,程序會把每個 object 的大小變爲最接近其大小的內存頁面倍數。然後從現有的空閒存儲結構體中查找,找到最合適的大小的空閒存儲塊,分配給它。如果空閒塊沒有用完,就把多餘的內存另外組成一個空閒存儲塊,掛到管理結構體上。如果緩存已滿,就根據 LRU 機制,把最舊的 object 釋放掉。

釋放緩存的過程是這樣的:有一個超時線程,檢測緩存中所有 object 的生存期,如果超初設定的 TTL(Time To Live)沒有被訪問,就刪除之,並且釋放相應的結構體及存儲內存。注意釋放時會檢查該存儲內存塊前面或後面的空閒內存塊,如果前面或後面的空閒內存和該釋放內存是連續的,就將它們合併成更大一塊內存。

整個文件緩存的管理,沒有考慮文件與內存的關係,實際上是將所有的 object 都考慮是在內存中,如果系統內存不足,系統會自動將其換到 swap 空間,而不需要 varnish 程序去控制。

varnish的程序環境:
/etc/varnish/varnish.params: 配置varnish服務進程的工作特性,例如監聽
的地址和端口,緩存機制;
/etc/varnish/default.vcl:配置各Child/Cache線程的緩存策略;
主程序:
    /usr/sbin/varnishd
CLI interface:
    /usr/bin/varnishadm
VCL配置文件重載程序:
    /usr/sbin/varnish_reload_vcl
varnish的緩存存儲機制( Storage Types):
  -s [name=]type[,options]  
    · malloc[,size]
        內存存儲,[,size]用於定義空間大小;重啓後所有緩存項失效;
    · file[,path[,size[,granularity]]]
        磁盤文件存儲,黑盒;重啓後所有緩存項失效;
    · persistent,path,size
        文件存儲,黑盒;重啓後所有緩存項有效;實驗;

通過yum安裝完varnish後,首先我們來看看varnish.params配置文件

# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings

# Set this to 1 to make systemd reload try to switch VCL without restart.
RELOAD_VCL=1

# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl  #指定默認的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=192.168.1.5
VARNISH_LISTEN_PORT=80 #指定監聽的端口

# Admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 #管理地址
VARNISH_ADMIN_LISTEN_PORT=6082

# Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret #口令文件

# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
VARNISH_STORAGE="file,/var/varnish/cache,256M" #這個是我們主要改的,存儲的位置,方法形式

# User and group for the varnishd worker processes
VARNISH_USER=varnish
VARNISH_GROUP=varnish

# Other options, see the man page varnishd(1)
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"    
varnish程序的選項:
            程序選項:/etc/varnish/varnish.params文件
                -a address[:port][,address[:port][...],默認爲6081端口; 
                -T address[:port],默認爲6082端口;
                -s [name=]type[,options],定義緩存存儲機制;
                -u user
                -g group
                -f config:VCL配置文件;
                -F:運行於前臺;

然後我們使用varnishadm來登陸接口
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
登陸進來使用help查看可用的命令

    
            配置文件相關:
                vcl.list 
                vcl.load:裝載,加載並編譯;
                vcl.use:激活;
                vcl.discard:刪除;
                vcl.show [-v] <configname>:查看指定的配置文件的詳細信息;
                
            運行時參數:
                param.show -l:顯示列表;
                param.show <PARAM>
                param.set <PARAM> <VALUE>
                
            緩存存儲:
                storage.list
                
            後端服務器:
                backend.list 

下面我們來介紹下VCL配置文件,裏面的功能是通過一種語言實現的。VCL有多個狀態引擎,狀態之間存在相關性,但狀態引擎彼此間互相隔離;每個狀態引擎可使用return(x)指明關聯至哪個下一級引擎;每個狀態引擎對應於vcl文件中的一個配置段,即爲subroutine。


13920922-f1e8b4fbf6c8b97e.png
image.png
vcl_recv的默認配置:
            
                sub vcl_recv {
                    if (req.method == "PRI") {
                        /* We do not support SPDY or HTTP/2.0 */
                        return (synth(405));
                    }
                    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);
                    }

                    if (req.method != "GET" && req.method != "HEAD") {
                        /* We only deal with GET and HEAD by default */
                        return (pass);
                    }
                    if (req.http.Authorization || req.http.Cookie) {
                        /* Not cacheable by default */
                        return (pass);
                    }
                        return (hash);
                    }
                }

裏面還有許許多多的變量

變量類型:
            內建變量:
                req.*:request,表示由客戶端發來的請求報文相關;
                    req.http.*
                        req.http.User-Agent, req.http.Referer, ...
                bereq.*:由varnish發往BE主機的httpd請求相關;
                    bereq.http.*
                beresp.*:由BE主機響應給varnish的響應報文相關;
                    beresp.http.*
                resp.*:由varnish響應給client相關;
                obj.*:存儲在緩存空間中的緩存對象的屬性;只讀;
                
                常用變量:
                    bereq.*, req.*:
                        bereq.http.HEADERS
                        bereq.request:請求方法;
                        bereq.url:請求的url;
                        bereq.proto:請求的協議版本;
                        bereq.backend:指明要調用的後端主機;
                        
                        req.http.Cookie:客戶端的請求報文中Cookie首部的值; 
                        req.http.User-Agent ~ "chrome"
                        
                        
                    beresp.*, resp.*:
                        beresp.http.HEADERS
                        beresp.status:響應的狀態碼;
                        reresp.proto:協議版本;
                        beresp.backend.name:BE主機的主機名;
                        beresp.ttl:BE主機響應的內容的餘下的可緩存時長;
                        
                    obj.*
                        obj.hits:此對象從緩存中命中的次數;
                        obj.ttl:對象的ttl值
                        
                    server.*
                        server.ip
                        server.hostname
                    client.*
                        client.ip                   
                
            用戶自定義:
                set 
                unset 

默認的VCL文件

vcl 4.0;

# Default backend definition. Set this to point to your content server.
backend default {
    .host = "192.168.31.201";
    .port = "80";
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.
}

sub vcl_backend_response {
    # Happens after we have read the response headers from the backend.
    #
    # Here you clean the response headers, removing silly Set-Cookie headers
    # and other mistakes your backend does.
}

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 acc

然後我們再在varnish主機上配置nginx來進行反代
測試實驗結果

[root@node1 ~]# curl -I  http://192.168.31.201:/index.html
HTTP/1.1 200 OK
Server: nginx/1.12.2
Date: Tue, 12 Feb 2019 12:59:11 GMT
Content-Type: text/html
Content-Length: 22
Connection: keep-alive
Last-Modified: Thu, 03 Jan 2019 14:07:05 GMT
ETag: "5c2e1709-16"
X-Varnish: 32770 3
Age: 10
Via: 1.1 varnish-v4

配置手動清除緩存

backend default {
    .host = "192.168.31.203";
    .port = "80";
}

sub vcl_recv {
    # Happens before we check if we have this in cache already.
    #
    # Typically you clean up the request here, removing cookies you don't need,
    # rewriting the request, etc.
     if (req.method == "PURGE") {
        return (purge);   //清除緩存
}

sub vcl_purge {
        return(synth(200,"success"));
}

vcl.load test1 /etc/varnish/default.vcl
200        
VCL compiled.
vcl.use test1
200        
VCL 'test1' now active

清除緩存的結果

[root@node1 ~]# curl -I -X PURGE http://192.168.31.201    
HTTP/1.1 200 success
Server: nginx/1.12.2
Date: Tue, 12 Feb 2019 13:49:13 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 240
Connection: keep-alive
X-Varnish: 56
Retry-After: 5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章