memcached
緩存服務器:
1.緩存:cache,無持久存儲功能
2.行掛失緩存bypass,而不是代理式緩存
3.僅提供緩存功能,存什麼,怎麼存全有客戶端決定
4.k/v cache,只能存儲可序列化數據
5.存儲項是非常簡單的:key,value,flag,expire time(過期時間)單數上限:1M
6.功能的實現一把依賴於memcached,一半是client
7.不能高可用,掛了緩存就丟失了
8.O(1)的執行效率
9.分佈式緩存互不通信的分佈式集羣
分佈式系統請求路由方法:取膜法,一致性哈希算法
10.緩存耗盡時基於LRU(最近最少使用)清理
緩存過期項:惰性清理機制,新的直接覆蓋舊的
memcached協議
客戶端要擁有連接memcached的適配器php-memcached
yum安裝就好
配置文件/etc/sysconfig/memcached
默認監聽11211/tcp,11211/udp
主程序 /usr/bin/memcached
協議格式:
文本格式
二進制格式
telnet文本交互:
常用命令
統計類:stats items | slabs |sizes
存儲類:set,add,replace,append,perpend
獲取數據類:get,delete,incr/decr
清空:flesh_all
add mykey 0 30 5 添加mykey
hello 內容hello
set mykey 0 30 5 設置mykey的值
hello
get mykey 獲取mykey值
0:標誌位
30:緩存ttl值時長,30秒後無法獲得
5:整個數據的長度
append mykey 0 300 11 追加內容,注意長度的修改,是指添加了多少個字符而不是添加到
prepend mkkey 0 300 3 同上,只不過是在前邊添加,想要兩個值之間帶空格就在字符數多幾個字符
incr key_name # 將key的值+1 key值要是數字
decr # -1
(常用於微博微信之類的贊轉發之類的計數)
flush all 清空緩存
程序常用選項
-m #:緩存空間大小,單位mb默認64
-c #:併發連接數,默認1024
-u username:程序運行者身份,一般要用普通用戶
-p Port:監聽的tcp端口
-u Port:監聽的udp端口
-l ip_addr:監聽的IP地址,默認本機所有IP地址
-M :一旦緩存空間耗盡的時候,想請求存儲緩存項換回錯誤信息,而非使用默認的lru算法
-f factor :用來指明chunk的增長因子,默認是1.25
-vv:詳細內容
-t #:線程數量,默認爲4,最好<cpu數
啓動服務一般選項
memcached -u -p -m -c $options
在環境文件中配置後,直接memcached就行
/etc/sysconfig/memcached
options項寫-a xxx之類的就行
memcached的認證功能
默認沒有認證機制,可以藉助SASL進行認證
SASL:簡單安全認證層
API:C++:libmemcached(c語言)
php:memcached:php-pecl-memcached
memcache :php-pecl-memcache
Varnish:web cache (page cache)
中小型web應用架構 圖
線程限制是針對域名來說的,單域名雙線程,所以,多個域名也可以提升性能
程序運行具有局部性特徵
空間局部性:
某一個數據被訪問過,離他較近的數據也有可能被訪問到
時間局部性:
某一個數據被訪問到,隨後有可能很快會被再次訪問到
熱區:一段時間內會有一個特別流行的數據,80%的訪問量被20%的數據承載(尤其是電商,流行商品,淘寶爆款),這些就叫熱區,其實就是局部性的表現,體現出緩存的價值,因爲緩存主要存放的及時熱區數據
時效性:緩存是會過期的,所以要具備過期處理邏輯
緩存清理:
過期清理
緩存溢出清理:LRU最近最少使用
緩存就是利用空間換取時間,在較短的時間內快速獲得結果
緩存命中率:命中次數/未命中次數+命中次數
(0,1)
頁面命中率:基於頁面數量進行衡量
字節命中率:基於頁面的大小,體積進行衡量
以上要有一個是收益OK的,那麼緩存就是有效的
緩存與否:
私有數據:private,例如郵箱等:只能放在私有緩存中
公共數據:public,例如電商的商品頁面:放在私有緩存和公有緩存
緩存種類:
私有緩存:瀏覽器緩存
公有緩存:reverse proxy,cache
如何分辨私有公有:
帶有某個標籤或者是存在cookie的都是私有的,沒有的就被認定是公有的
緩存處理的步驟
接受請求--->解析請求(提取請求首部中的URL及其他首部)---->查詢緩存--->新鮮度檢測(是不是在有效期)--->檢查元數據是不是改變,如果沒改變--->構建響應報文-->發送響應--->記錄日誌(類似於httpd的combined)
過期檢查機制:
每個緩存都是會有服務器加一個過期時間.在這個時間內都是有緩存返回的,如果過期了或者沒有緩存,就反代到後端服務器,後端服務器發送數據和過期時間給緩存和請求
首部:HTTP/1.0
Expire:絕對時間:xxx-xxx
HTTP/1.1
Cache-Control:maxage=相對時長,過多長時間過期
Cache-Control:s-maxage=公共緩存時長
條件檢查機制:validation
(1)LASTMODIFIED:最近修改時間
IF MOFIFIED SINCE:從上次開始是不是修改過時間
請求數據到緩存服務器上,如果超出有效時間,緩存服務器向後端服務器發送一個請求報文,詢問是不是修改了,如果是,就由後端服務器來發送數據,沒有的話就是有緩存發送
(2)Etag:資源標籤
if-none-match:標籤有沒變換
基本上和上邊相同,只是尋問的是標籤有沒有變化
兩者結合:超時有效時長的,向後端服務器發送條件檢查
開源解決方案:
squid:
varnish:在非常大的併發連接數下,varnish不是很穩定
varnish:絕大多數站點都是varnish www.varnish-cache.org 最新穩定版本4.1.3 (分支5.0|4.1|4.0)
Architecture 圖
組織架構
management進程
child/cache進程:包含多種類型的線程
accept worker expiry
shared memeory log:
統計數據的計數器
日誌區域
配置接口:VCL
VCL complier--->c complier------->shared object
上午第二節課
環境文件
配置文件
/etc/varnish/default.vcl配置緩存工作(child/cache)
/etc/varnish/varnish.params配置varnish自身(端口之類的)
主程序
CLI interface
varnishadm
shared log
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtest
/usr/bin/varnishtop
varnishtest:模擬varnish的客戶端,測試varnish的工作是不是正常
systemd unitfile
varnish.service
varnishlog
varnishncsa:日誌持久化服務,每個多長時間讀取次日誌
varnish的緩存存儲機制
(1)malloc[,size]
內存存儲
(2)file[path[,size[,granularity]]]
文件存儲,黑盒,重啓後緩存失效
(3)persistent,path,size
文件存儲,黑盒,重啓不失效,但是還在測試
varnish程序的選項
(1)程序選項 /etc/varnish/varnish.params
-a IP地址:port
服務接口,不能是127,默認6081
-T IP地址:port
管理接口,默認6082
-s [name]=type[,options]
定義緩存存儲機制
-u user
-g group
定義運行身份
-f config
VCL配置文件
-F
前臺運行
(2)運行時參數(運行時可以更改的)
-p param=value
-r param[,param..]運行時不可以更改,只讀
大多數運行參數都有默認值不用設定,必要設定時候要在varnish.params定義,在程勳運行前定義
在底下的DEMON_OPTS
例如:
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
具體配置
6081可以改
6082是管理接口,也可以改
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
最小/最大線程池數量,超時時間
VARNISH_STORAGE="file,/var/lib/varnish/varnish_storage.bin,1G"
文件存儲
VARNISH_STORAGE="malloc,1G"
內存存儲
事實上大多時候都不需要更改直接使用,主要還是VCL
varnish_reload_vcl:vcl配置文件重載程序
varnishadm -S /etc/varnish/sercet -T address:port
help獲取命令列表
配置文件相關
vcl.list:列出vcl文件有哪些
load:裝載,加載並編譯
vcl.load testconfig1 default.vcl
use:激活
vcl.use testconfig1 激活了,生效了
discard:刪除,最好先激活另一個後在刪除上一個
運行時參數
param.show:顯示參數列表
show<param>顯示某個參數配置
set<PARAM><VALUE>設定
緩存存儲
storage.list
後端服務器:
backend.list
VCL:域專有類型的配置語言
state engine:狀態引擎
VCL有多個狀態引擎.且之間存在相關性,但是彼此間互相隔離,每個狀態引擎可使用return指明關聯至那個下一級引擎
圖
vcl_recv--->vcl_pipe
收到後不知道做什麼直接送到後端
vcl_recv--->vcl_error
收到後不允許給他數據或者直接請求就是錯的
vcl_pass:多加的處理邏輯,可以額外做一些處理的設定
vcl_purge:緩存的修剪
varnish 4:
vcl_recv ---->vcl_hash
(1)hit:vcl_hit--->vcl_deliver
(2)pass,hit for pass:vcl_pass--->vcl_backend_fetch-->_response-->vcl_deliver
(3)miss:vcl_miss--->[vcl_pass--->]vcl_backend_fetch-->_response-->vcl_deliver
(4)purge:vcl_purge--->vcl_synth
(5)pipe:vcl_pipe
(6)busy:vcl_waiting
vcl語法格式
(1)支持註釋符
//:單行註釋
/*...*/:多行註釋
#:註釋
(2)sub $name:定義子例程;sub vcl_recv{..}只對vcl_recv有效
(3)不支持循環,但是支持條件判斷
(4)有大量的內建變量,生效位置有特定要求
(5)使用終止語句return決定下一個狀態引擎;但是沒有返回值
(6)操作符
=:賦值
==:等值判斷
!:取反
~:匹配
&&:邏輯與
||:邏輯或
>,<,>=,<=
(7)語句使用;結尾
變量類型
內建變量:
req.*:request,由客戶端發來的請求報文相關的衆多數據
req.http.*
req.http.User-Agent:客戶端瀏覽器類型
.Referer:從哪裏引用過來的
.method:get等
各引擎都可用,都是隻讀只寫
bereq.*:backend 由varnish發給後端的請求
berep.http.*
beresp.*:有後端響應給varnish的
beresp.http.*
obj.*:發送給緩存服務器的
resp.*:響應給前端請求的
常用變量
bereq.*:
bereq.http.HEADERS
bereq.request:請求方法
.url:請求的url
.proto:請求的協議版本
.backend:指明要調用的後端主機
beresp.*:
bereq.http.HEADERS
.status:響應的狀態碼
.proto:協議版本
.backend.name:BE主機的主機名
.ttl:BE主機響應內容的餘下的可緩存時長
obj.*:
obj.hits:當前正在訪問的緩存的命中次數(這一次)
.ttl:對象的ttl值,緩存時長
server.*
server.ip
.hostname
client.*
.ip
下午第一節課
set:設置一個變量
unset:取消一個變量
用戶自定義:
事例1:強制對某類資源的請求不檢查緩存
vcl_recv{
if (req.url ~ "(?i)^/(login|admin)") {
return(pass);
}
}
事例2:對於特定類型的資源,例如公開的圖片等,取消其私有標誌,並強行設定器可以由varnish緩存的時長
vcl_backend_response{
if (beresp.http.caceh-control !~ "s-maxage") {
if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)$") {
unset beresp.http.Set-Cppkie;
set beresp.ttl=3600s;
}
}
}
緩存對象的修剪:purge ban
purge:
(1)sub vcl_purge {
return(synth(200,"purged自己定義"));
}
(2)要在recv中定義那些請求到purge中
if (req.method == "PURGE") {
return(purge);
}
(3)定義訪問控制列表
acl purgers {
"127.0.0.0"/8;
"172.16.0.0"/16;
}
sub vcl_recv {
if (req.method == "PURGE") {
if(!dlient.ip ~ purgers){
return(405,"Purging not allowed for" = + client.ip));
}
}
}
如何設定使用多個後端主機:
backend name {
.host = " ";
.port = " ";
}
sub vcl_recv {
if (req.url ~ "(?i)\.php$") {
set req.backend_hint = appsrv;
} else {
set req.backend_hint = default;
}
}
}
後端多個主機不做分離式做負載均衡
varnish做director
varnish module
使用前要先導入
import directors
sub vcl_init:處理任何請求之前要執行的vcl代碼,主要用於初始化VMODs
vcl_fini:所有的請求都退出後,在vcl配置被丟棄的時候處理調用,主要用於清理VMODs
調度方法:random,hash,round_robin()
import directors;
sub vcl_init{
newbar = director.round_robin();
自定義組名 .調度算法
bar.add_backend(server1);
bar.add_backend(server2);
}
sub vcl_recv {
set req.backend_hint = newbar.backend();
}
BE健康狀態檢查
backend BE_NAME{
.host
.port
.probe={
.url:檢測要請求的url,默認爲主頁
.request:指明打出請求報文怎麼發
.timeout:檢測的超時時長
.inteval:檢查頻度,多長時間檢查一次
.window = #:基於最近的多少次檢查判斷健康狀態
.threshold = #:至少幾次是成功才認定是健康的
.expected_response:期望的響應碼,默認是200
}
}
也可以
probe NAME {
.url:檢測要請求的url,默認爲主頁
.request:指明打出請求報文怎麼發
.timeout:檢測的超時時長
.inteval:檢查頻度,多長時間檢查一次
.window = #:基於最近的多少次檢查判斷健康狀態
.threshold = #:至少幾次是成功才認定是健康的
.expected_response:期望的響應碼,默認是200
}
然後在.host下邊
.probe = NAME;
varnish的運行時參數:查看參數 param.show -l
線程模型:
cache-worker
cache-main
ban lurker
acceptor
epoll/kqueue*
...
線程相關的參數
在線程池內部,其每一個請求有一個線程處理;其worker線程的最大數決定了varnish的併發響應能力
thread_pools :線程池個數,小於等於cpu核心數
thread_pool_max:調整每個線程池的最大工作線程數量,默認5000個
最大併發數上邊兩個相乘
thread_pool_min:......
param.set thread_poll_max 1000(但是重啓不保存,編輯配置文件)
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
記住要用-p指定,每一個都要,不可以一個-p指多個參數
thread_poll_timeout:默認10秒
_add_delay:創建線程之間要不要有間隔,默認0
_destroy_delay:多長時間清理一個線程,默認10毫秒
客戶端命令的使用
/usr/bin/varnishhist
/usr/bin/varnishlog
/usr/bin/varnishncsa
/usr/bin/varnishstat
/usr/bin/varnishtest
/usr/bin/varnishtop
日誌區域
計數器
日誌信息
/usr/bin/varnishstat查看統計數據
varnishstat -1:持續刷新類似watch -n
-f:指向顯示那些字段,-1出來的都是字段
-1 -f xxxx
-l:那些字段可以跟-f使用
MAIN.cache_miss
MAIN.cache_hit 重點關注的兩項,可以計算命中率
/usr/bin/varnishtop顯示日誌,對日誌做排序
varnishtop -1:持續性顯示
-i:查看指定標籤信息,標籤名去-1信息裏邊找,多個","隔開
-I:同-i,但是支持正表
-x:排除列表,不顯示某個標籤
-X:支持正表的-x
/usr/bin/varnishlog正兒八經的顯示日誌本身的
varnishlog
/usr/bin/varnishncsa將日誌以combined的格式顯示,就是httpd的日誌格式
varnishncsa -f:指定日誌記錄什麼,就是httpd的那些%的東西
想保存起來就執行/usr/lib/systemd/system/varnishncsa.service
systemctl start varnishncsa.service
vcl可以做url重寫,使用一個內建函數
一個客戶端有多個域名,使用hash算法來命中
hash_data():指明hash計算的數據,減少差異以提升命中率
regsub(str,regex,sub):正則表達式的模式替換,吧str中第一次被regex匹配到的替換爲sub
regsuball():全部替換,主要用於url重寫
return()
ban(expression):清理緩存,後跟普通表達式
ban_url(regex):清理緩存,後跟正表
最後一節課最後的hash_data
synth(status,"string"):purge,一次只清理一個url緩存對象
實踐作業
前段nginx將用戶請求調度到兩個varnish,並保證命中率,hash他的url,map和consistent的hash算法,varnish要方向代理用戶請求到後端主機,後端主機上部署以個wordpress,並且把請求分發到三個主機上的時候有什麼不同
生成靜態頁面,當服務器掛了,就定到靜態頁面服務器上,降級xx的概念
博客作業,以上所有內容
haproxy和tomcat