1、簡述HA cluster原理
2身坐、keepalived實(shí)現(xiàn)主從耿战、主主架構(gòu)
3蛋叼、簡述http協(xié)議緩存原理及常用首部講解
4、簡述回源原理和CDN常見多級(jí)緩存
5、varnish實(shí)現(xiàn)緩存對象及反代后端主機(jī)
1狈涮、簡述HA cluster原理
高可用集群(High Availability Cluster)簡單的理解就是多個(gè)節(jié)點(diǎn)作為一個(gè)整體向用戶提供一組網(wǎng)絡(luò)資源狐胎。如果某個(gè)節(jié)點(diǎn)失效,它的備用節(jié)點(diǎn)將在幾秒鐘的時(shí)間內(nèi)接管它的職責(zé)歌馍。用戶將完全感受不到這個(gè)過程握巢,因此,對于用戶而言松却,集群永遠(yuǎn)不會(huì)停機(jī)暴浦。高可用集群軟件的主要作用就是實(shí)現(xiàn)故障檢查和業(yè)務(wù)切換的自動(dòng)化。只有兩個(gè)節(jié)點(diǎn)的高可用集群又稱為雙機(jī)熱備晓锻,即使用兩臺(tái)服務(wù)器互相備份歌焦。
2、keepalived實(shí)現(xiàn)主從带射、主主架構(gòu)
首先需要同步時(shí)間同规,時(shí)間不同步的話就很可能會(huì)出錯(cuò)
然后下載keepalived安裝包,默認(rèn)在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 #郵件服務(wù)器可以是自己券勺;
smtp_connect_timeout 30 #郵件服務(wù)器鏈接超時(shí)時(shí)長
router_id rt1 #router標(biāo)識(shí)一個(gè)組內(nèi)不同的router
vrrp_mcast_group4 224.0.0.1 #組播地址
}
vrrp_instance VI_1 { #組名VI_1
state MASTER
interface ens33
virtual_router_id 51 #整個(gè)虛擬組的id,同組配置須保持一致
priority 100
advert_int 1 #一秒檢查一次
authentication {
auth_type PASS #simple認(rèn)證
auth_pass 12345678 #最大支持8位
}
virtual_ipaddress {
#<IPADDR>/<MASK> brd <IPADDR> dev <STRING> scope <SCOPE>
192.168.31.240/24 dev ens33 label ens33:0
}
}
然后將配置文件傳給另一臺(tái)主機(jī)
scp keepalived.conf root@192.168.31.201:/etc/keepalived/
在這一臺(tái)主機(jī)里我們只需要簡單的修改幾項(xiàng)
router_id rt2
state BACKUP
ppriority 95 #低一點(diǎn)
配置到這里就結(jié)束了灿里,很簡單关炼。接下來我們就可以開始測試了
先在backup機(jī)上開啟keepalive進(jìn)程
可以看到已經(jīng)拿到地址了
現(xiàn)在我們在master上開啟進(jìn)程
發(fā)現(xiàn)被更高的優(yōu)先級(jí)搶走了
然后我們可以抓包查看他們互相通告的信息
雙主模式
但如果這樣配置的話就只有一臺(tái)在工作,另一臺(tái)一直是備用的匣吊,我們可以在主機(jī)上分別配置兩個(gè)虛擬路由器儒拂,假如A,B兩臺(tái)主機(jī)我們想要讓他們同時(shí)工作起來,可以讓A為第一個(gè)虛擬路由器的master色鸳,則B就是第二個(gè)虛擬路由器的master然后我們就有了兩個(gè)VIP社痛,但是有了兩個(gè)VIP其他主機(jī)怎么與我們通信實(shí)現(xiàn)負(fù)載均衡呢,這個(gè)時(shí)候我們就需要一個(gè)新的調(diào)度器命雀,但我們配置keepalive本來就是為了增強(qiáng)調(diào)度器的冗余安全性蒜哀,如果引入了新的節(jié)點(diǎn)豈不是本末倒置。
這時(shí)我們可以使用DNS服務(wù)吏砂,DNS本來就是主從互備不存在單點(diǎn)性且只需要我們在一個(gè)域名里添加兩條A記錄就可以達(dá)到輪詢負(fù)載均衡的目的撵儿。
編輯配置文件增加一個(gè)虛擬路由器配置:
#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
}
}
然后我們抓包看
每一臺(tái)主機(jī)都分別獲取到了一個(gè)IP地址如果我們down了其中一臺(tái)主機(jī),則ip地址會(huì)跑到另一臺(tái)上狐血,測試一下看看
則簡單的實(shí)驗(yàn)就完成了
我們可以定義發(fā)生變化時(shí)執(zhí)行指定的腳本
通知腳本的使用方式:
示例通知腳本:
#!/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
#腳本的調(diào)用方法淀歇,寫在虛擬路由器中
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
3、簡述http協(xié)議緩存原理及常用首部講解
(1)強(qiáng)制緩存機(jī)制(過期時(shí)間機(jī)制)
基本原理:
客戶端第一次請求服務(wù)端時(shí)匈织,服務(wù)端把緩存規(guī)則信息添加到header中浪默,客戶端通過這些信息判斷是否能緩存。若能強(qiáng)制緩存,則header中會(huì)有兩個(gè)字段來標(biāo)記緩存失效的時(shí)間(expires或cache-control)浴鸿。在客戶端第一次請求并添加緩存后井氢,以后每次客戶端的請求響應(yīng)數(shù)據(jù)都是緩存服務(wù)器提供的,不會(huì)再是服務(wù)端岳链。緩存服務(wù)器根據(jù)cache-control字段來判斷是否使用花竞、是否更新、何時(shí)更新緩存掸哑。
- expires约急,緩存過期時(shí)間
- cache-control有下面幾個(gè)參數(shù):
- public,允許客戶端和代理使用緩存苗分,即客戶端請求的資源可以被任何緩存區(qū)所緩存
- private厌蔽,允許客戶端使用緩存,即對于某個(gè)用戶的響應(yīng)信息不能被共享緩存區(qū)所緩存
- max-age摔癣,緩存最大失效時(shí)長(單位為秒)
- no-cache奴饮,關(guān)閉強(qiáng)制緩存,需要使用對比緩存
- no-store择浊,所有內(nèi)容都不緩存
(2)對比緩存機(jī)制(條件式緩存機(jī)制):
基本原理:
- a)緩存命中的情況:客戶端向緩存服務(wù)器請求獲取緩存header標(biāo)識(shí)戴卜,客戶端獲取標(biāo)識(shí)后,向后端服務(wù)器發(fā)送header標(biāo)識(shí)規(guī)則琢岩,若未失效便通知客戶端使用緩存服務(wù)器緩存的數(shù)據(jù)(狀態(tài)碼304)投剥。
- b)緩存未命中的情況:客戶端向緩存服務(wù)器請求獲取緩存header標(biāo)識(shí),客戶端獲取標(biāo)識(shí)后担孔,向后端服務(wù)器發(fā)送header標(biāo)識(shí)規(guī)則江锨,若失效便通知客戶端不使用緩存服務(wù)器緩存的數(shù)據(jù)(狀態(tài)碼200),并更新緩存糕篇。
對比緩存標(biāo)識(shí):
last-modified/if-modfied-since:資源最后的修改時(shí)間戳
etag/if-none-match:資源校驗(yàn)碼
4啄育、簡述回源原理和CDN常見多級(jí)緩存
回源是指瀏覽器在發(fā)送請求報(bào)文時(shí),響應(yīng)該請求報(bào)文的是源站點(diǎn)的服務(wù)器拌消,而不是各節(jié)點(diǎn)上的緩存服務(wù)器灸撰,那么這個(gè)過程相對于通過各節(jié)點(diǎn)上的緩存服務(wù)器來響應(yīng)的話就稱作為回源∑纯玻回源的請求或流量太多的話,有可能會(huì)讓源站點(diǎn)的服務(wù)器承載著過大的訪問壓力完疫,進(jìn)而影響服務(wù)的正常訪問泰鸡。
CDN(Content Delivery Network)內(nèi)容分發(fā)網(wǎng)絡(luò),其思路是盡可能避開網(wǎng)絡(luò)上的瓶頸壳鹤,通過在網(wǎng)絡(luò)邊緣部署邊緣服務(wù)器盛龄,依靠CDN中心平臺(tái)的負(fù)載均衡、內(nèi)容分發(fā)及調(diào)度等功能,使用戶就近獲取所需的內(nèi)容余舶,降低網(wǎng)絡(luò)擁堵啊鸭,提高用戶訪問響應(yīng)速度和命中率。所以基本上CDN就是廣泛采用各種緩存服務(wù)器匿值,使得用戶的請求直接由這些緩存服務(wù)器響應(yīng)赠制,加快了響應(yīng)速度;只有在用戶請求的資源在緩存服務(wù)器上沒有找到或者請求訪問的資源在源站點(diǎn)服務(wù)器上已經(jīng)修改過的情況下挟憔,緩存服務(wù)器才會(huì)去訪問源站點(diǎn)服務(wù)器以獲取最新的資源钟些。簡單的來說就是在多個(gè)地方設(shè)置緩存服務(wù)器,使當(dāng)?shù)氐挠脩艨芍苯釉L問當(dāng)?shù)氐木彺娣?wù)器而不必頻繁的去訪問源站绊谭,減少根服務(wù)器的壓力政恍。
CDN節(jié)點(diǎn)的緩存機(jī)制也是遵循h(huán)ttp協(xié)議,因此也會(huì)受到Cache-Control等字段的影響达传。如果緩存的時(shí)間太短就會(huì)頻繁的向根源服務(wù)器發(fā)起請求篙耗,增加源站點(diǎn)的負(fù)擔(dān),如果緩存時(shí)間太長又有可能涉及到更新的問題宪赶,這就需要設(shè)計(jì)者根據(jù)實(shí)際情況去設(shè)計(jì)宗弯。
5、varnish實(shí)現(xiàn)緩存對象及反代后端主機(jī)
緩存原理
Varnish 與一般服務(wù)器軟件類似逊朽,分為 master 進(jìn)程和 child 進(jìn)程罕伯。Master 進(jìn)程讀入存儲(chǔ)配置文件,調(diào)用合適的存儲(chǔ)類型叽讳,然后創(chuàng)建 / 讀入相應(yīng)大小的緩存文件追他,接著 master 初始化管理該存儲(chǔ)空間的結(jié)構(gòu)體,然后 fork 并監(jiān)控 child 進(jìn)程岛蚤。Child 進(jìn)程在主線程的初始化的過程中邑狸,將前面打開的存儲(chǔ)文件整個(gè) mmap 到內(nèi)存中,此時(shí)創(chuàng)建并初始化空閑結(jié)構(gòu)體涤妒,掛到存儲(chǔ)管理結(jié)構(gòu)體单雾,以待分配。Child 進(jìn)程分配若干線程進(jìn)行工作她紫,主要包括一些管理線程和很多 worker 線程硅堆。
接著,開始真正的工作贿讹,varnish 的某個(gè)負(fù)責(zé)接收新 HTTP 連接線程開始等待用戶渐逃,如果有新的 HTTP 連接過來,它總負(fù)責(zé)接收民褂,然后喚醒某個(gè)等待中的線程茄菊,并把具體的處理過程交給它疯潭。Worker 線程讀入 HTTP 請求的 URI,查找已有的 object面殖,如果命中則直接返回并回復(fù)用戶竖哩。如果沒有命中,則需要將所請求的內(nèi)容脊僚,從后端服務(wù)器中取過來相叁,存到緩存中,然后再回復(fù)吃挑。
分配緩存的過程是這樣的:它根據(jù)所讀到 object 的大小钝荡,創(chuàng)建相應(yīng)大小的緩存文件。為了讀寫方便舶衬,程序會(huì)把每個(gè) object 的大小變?yōu)樽罱咏浯笮〉膬?nèi)存頁面倍數(shù)埠通。然后從現(xiàn)有的空閑存儲(chǔ)結(jié)構(gòu)體中查找,找到最合適的大小的空閑存儲(chǔ)塊逛犹,分配給它端辱。如果空閑塊沒有用完,就把多余的內(nèi)存另外組成一個(gè)空閑存儲(chǔ)塊虽画,掛到管理結(jié)構(gòu)體上舞蔽。如果緩存已滿,就根據(jù) LRU 機(jī)制码撰,把最舊的 object 釋放掉渗柿。
釋放緩存的過程是這樣的:有一個(gè)超時(shí)線程,檢測緩存中所有 object 的生存期脖岛,如果超初設(shè)定的 TTL(Time To Live)沒有被訪問朵栖,就刪除之,并且釋放相應(yīng)的結(jié)構(gòu)體及存儲(chǔ)內(nèi)存柴梆。注意釋放時(shí)會(huì)檢查該存儲(chǔ)內(nèi)存塊前面或后面的空閑內(nèi)存塊陨溅,如果前面或后面的空閑內(nèi)存和該釋放內(nèi)存是連續(xù)的,就將它們合并成更大一塊內(nèi)存绍在。
整個(gè)文件緩存的管理门扇,沒有考慮文件與內(nèi)存的關(guān)系,實(shí)際上是將所有的 object 都考慮是在內(nèi)存中偿渡,如果系統(tǒng)內(nèi)存不足臼寄,系統(tǒng)會(huì)自動(dòng)將其換到 swap 空間,而不需要 varnish 程序去控制溜宽。
varnish的程序環(huán)境:
/etc/varnish/varnish.params: 配置varnish服務(wù)進(jìn)程的工作特性脯厨,例如監(jiān)聽
的地址和端口,緩存機(jī)制坑质;
/etc/varnish/default.vcl:配置各Child/Cache線程的緩存策略合武;
主程序:
/usr/sbin/varnishd
CLI interface:
/usr/bin/varnishadm
VCL配置文件重載程序:
/usr/sbin/varnish_reload_vcl
varnish的緩存存儲(chǔ)機(jī)制( Storage Types):
-s [name=]type[,options]
· malloc[,size]
內(nèi)存存儲(chǔ),[,size]用于定義空間大形卸蟆稼跳;重啟后所有緩存項(xiàng)失效;
· file[,path[,size[,granularity]]]
磁盤文件存儲(chǔ)吃沪,黑盒汤善;重啟后所有緩存項(xiàng)失效;
· persistent,path,size
文件存儲(chǔ)票彪,黑盒红淡;重啟后所有緩存項(xiàng)有效;實(shí)驗(yàn)降铸;
通過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 #指定默認(rèn)的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 #指定監(jiān)聽的端口
# 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" #這個(gè)是我們主要改的,存儲(chǔ)的位置推掸,方法形式
# 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程序的選項(xiàng):
程序選項(xiàng):/etc/varnish/varnish.params文件
-a address[:port][,address[:port][...]桶蝎,默認(rèn)為6081端口;
-T address[:port]谅畅,默認(rèn)為6082端口登渣;
-s [name=]type[,options],定義緩存存儲(chǔ)機(jī)制毡泻;
-u user
-g group
-f config:VCL配置文件胜茧;
-F:運(yùn)行于前臺(tái);
然后我們使用varnishadm來登陸接口
varnishadm -S /etc/varnish/secret -T 127.0.0.1:6082
登陸進(jìn)來使用help查看可用的命令
配置文件相關(guān):
vcl.list
vcl.load:裝載仇味,加載并編譯呻顽;
vcl.use:激活;
vcl.discard:刪除邪铲;
vcl.show [-v] <configname>:查看指定的配置文件的詳細(xì)信息芬位;
運(yùn)行時(shí)參數(shù):
param.show -l:顯示列表;
param.show <PARAM>
param.set <PARAM> <VALUE>
緩存存儲(chǔ):
storage.list
后端服務(wù)器:
backend.list
下面我們來介紹下VCL配置文件带到,里面的功能是通過一種語言實(shí)現(xiàn)的昧碉。VCL有多個(gè)狀態(tài)引擎,狀態(tài)之間存在相關(guān)性揽惹,但狀態(tài)引擎彼此間互相隔離被饿;每個(gè)狀態(tài)引擎可使用return(x)指明關(guān)聯(lián)至哪個(gè)下一級(jí)引擎;每個(gè)狀態(tài)引擎對應(yīng)于vcl文件中的一個(gè)配置段搪搏,即為subroutine狭握。
vcl_recv的默認(rèn)配置:
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);
}
}
里面還有許許多多的變量
變量類型:
內(nèi)建變量:
req.*:request,表示由客戶端發(fā)來的請求報(bào)文相關(guān)疯溺;
req.http.*
req.http.User-Agent, req.http.Referer, ...
bereq.*:由varnish發(fā)往BE主機(jī)的httpd請求相關(guān)论颅;
bereq.http.*
beresp.*:由BE主機(jī)響應(yīng)給varnish的響應(yīng)報(bào)文相關(guān)哎垦;
beresp.http.*
resp.*:由varnish響應(yīng)給client相關(guān);
obj.*:存儲(chǔ)在緩存空間中的緩存對象的屬性恃疯;只讀漏设;
常用變量:
bereq.*, req.*:
bereq.http.HEADERS
bereq.request:請求方法;
bereq.url:請求的url今妄;
bereq.proto:請求的協(xié)議版本郑口;
bereq.backend:指明要調(diào)用的后端主機(jī);
req.http.Cookie:客戶端的請求報(bào)文中Cookie首部的值盾鳞;
req.http.User-Agent ~ "chrome"
beresp.*, resp.*:
beresp.http.HEADERS
beresp.status:響應(yīng)的狀態(tài)碼犬性;
reresp.proto:協(xié)議版本;
beresp.backend.name:BE主機(jī)的主機(jī)名腾仅;
beresp.ttl:BE主機(jī)響應(yīng)的內(nèi)容的余下的可緩存時(shí)長乒裆;
obj.*
obj.hits:此對象從緩存中命中的次數(shù);
obj.ttl:對象的ttl值
server.*
server.ip
server.hostname
client.*
client.ip
用戶自定義:
set
unset
默認(rèn)的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主機(jī)上配置nginx來進(jìn)行反代
測試實(shí)驗(yàn)結(jié)果
[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
配置手動(dòng)清除緩存
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
清除緩存的結(jié)果
[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