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