热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

varnish的缓存加速,以及动静分离,负载均衡

650)this.srchttp:www.itdaan.comimgs95244a3136d56729023a64c587f589f4a94

wKiom1Np64iigchlAAB3BEcos9Q821.jpg

一个简单的拓扑如上,varnish1 上还同时开了nginx,用来做静态的http,app1和app2 是nginx+fastcgi,这个拓扑主要做的是Discuz!论坛的动静分离,以及app的负载均衡,varnish起到个反向代理和缓存加速的功能。varnish1:192.168.1.151,172.16.0.51 app1:172.16.0.52

app3:172.16.0.54

varnish 简介

varnish的缓存方式:1.malloc,通过malloc获取内存,简单,速度。2.mmap file,创建文件缓存。 3.persistent(experimental):与file的功能相同,但可以持久存储数据(即重启varnish数据时不会被清除);仍处于测试期;
Grace mode如果后端需要长时间来生成一个对象,会有一个线程堆积的风险。为了避免这种情况,可以使用优雅模式(grace mode),也就是说让varnish 提供一个旧的版本,然后从后端生成新的目标版本。比如 set beresp.grace=30m,意思在30min 内复制旧的请求结果给客户端。Saint mode有时候,服务器会发出随机错误,这时就需要更加优雅的方式来处理,这种方式就叫 神圣模式(saint mode)。神圣模式允许抛弃一个后端服务器,或者另一个尝试的后端服务器或者 cache 中服务陈旧的内容。 Varnish运行时会同时启动两个进程,management进程和child进程(也叫cache进程)。management进程主要实现应用新的配置,编译vcl,监控varnish,初始化varnish以及提供一个命令接口。management进程会每隔几秒试探child进程以判断其是否正常运行,如果在指定时间内未得到child的响应,management会重启child进程。Child进程包含多种类型的线程:Acceptor线程:接收新的连接请求并响应;Worker线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多;Expiry线程:从缓存中清理过期内容;

安装配置varnish

在yum中新建个varnish.repovarnish.repo[varnish-3.0]
name=Varnish 3.0 for Enterprise Linux el6 - $basearch
baseurl=http://repo.varnish-cache.org/redhat/varnish-3.0/el6/$basearch
enabled=1
gpgcheck=0
#gpgkey=
file:///etc/pki/rpm-gpg/RPM-GPG-KEY-VARNISH
[root@varnish1 ~]# yum install varnish-3.0.4 -y[root@varnish1 ~]# vim /etc/sysconfig/varnish #varnish 的配置文件
NFILES = 131072 #打开的最大文件数
MEMLOCK = 82000# 82M,日志使用的共享内存
NPROCS = "unlimited" #最大的线程数
RELOAD_VCL = 1 # 每次重启都重新编译加载vcl。
VARNISH_VCL_COnF=/etc/varnish/default.vcl #默认使用的vcl文件
VARNISH_LISTEN_PORT=80 # vanish 监听的端口
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1 #
VARNISH_ADMIN_LISTEN_PORT=6082# varnish 管理监听的ip和端口
VARNISH_SECRET_FILE=/etc/varnish/secret #varnish 管理的 秘钥文件
VARNISH_MIN_THREADS=50 #varnish 启动的最小线程数
VARNISH_MAX_THREADS=1000 #最大线程数
VARNISH_THREAD_TIMEOUT=120 # 线程的超时过期时间,线程空闲超过设定的时间,线程就会被释放掉。
#VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin #varnish 使用文件来存储
#VARNISH_STORAGE_SIZE=1G #使用多大的文件
VARNISH_MEMORY_SIZE=100M #varnish 使用内存来存储
VARNISH_STORAGE="malloc,${VARNISH_MEMORY_SIZE}" #varnish使用malloc方式来缓存。
#VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}" #varnish使用file的方式缓存。
VARNISH_TTL=120 #缺省TTL
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
-f ${VARNISH_VCL_CONF} \
-T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
-t ${VARNISH_TTL} \
-w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
-u varnish -g varnish \
-S ${VARNISH_SECRET_FILE} \
-s ${VARNISH_STORAGE}"

#######################################################################

-a:监听地址和端口-f:vcl 配置文件-T:管理端口-t:缺省TTL,缓存中所有object的生命周期,如果缓存过期(ttl),则删除,释放相应的存储内存。-w :设定工作线程-S :秘钥文件-s: 存储方式(内存,文件)以及大小
[root@varnish1 ~]# vim /etc/varnish/default.vcl #vcl的配置文件probe staticcheck {  .url = "/test.html"; #请求的url  .interval = 60s; #探测的周期  .timeout = 3s; # 每次探测的过期时长  .window = 8; #基于最近多少次的探测进行,默认是8;  .threshold = 4; #在.window中指定的次数中,至少有多少次是成功的才判定后端主机正健康运行;  .initial = 3; #Varnish启动时对后端主机至少需要多少次的成功探测,默认同.threshold;  .expected_respOnse= 200; #期望后端主机响应的状态码,默认为200;}#健康状态检查,检查静态probe dycheck {  .url = "/test.php";  .interval = 60s;  .timeout = 3s;  .window = 8;  .threshold = 4;  .initial = 3;  .expected_respOnse= 200;}#健康状态检查,检查动态backend app1 {  .host = "172.16.0.52";  .port = "80";  .probe = dycheck;}backend app2 {  .host = "172.16.0.54";  .port = "80";  .probe = dycheck;}backend s1 {  .host = "127.0.0.1";  .port = "8080";  .probe = staticcheck;}#定义2个app主机,1个静态主机director appservers  round-robin {#       .retries = 5;        {.backend = app1;}        {.backend = app2;}}#定义一个负载均衡组,使用round-robin算法。acl purgers {        "127.0.0.1";        "192.168.1.0"/24;}#定义 可以purge的acl。sub vcl_recv {        if (req.request == "PURGE") {                if (!client.ip ~ purgers) {                        error 405 "Method not allowed";                } #如果client 不是本地或者是192.168.1.0/24 网段的就不允许purge。                      return (lookup);        }        if (req.http.x-forwarded-for) {            set req.http.X-Forwarded-For =                req.http.X-Forwarded-For + ", " + client.ip;        } else {            set req.http.X-Forwarded-For = client.ip;        } #定义后端web 可以记录真实的client的ip。        if (req.request != "GET" &&            req.request != "HEAD" &&            req.request != "PUT" &&            req.request != "POST" &&            req.request != "TRACE" &&            req.request != "OPTIONS" &&            req.request != "DELETE") {            return (pipe);        } #如果请求的不是get,head,put,post,trace,options,delete 就直接给pipe。        if (req.http.Authenticate || req.http.Authorization) {                return (pass);        } #请求的有认证信息的,直接给pass,交给后端处理。        if (req.request != "GET" && req.request != "HEAD"){                return (pass);        }# 请求的不是get,head方法,直接给pass,交给后端处理。        if (req.url ~ "^/$") {                unset req.http.COOKIE;        } #把首页去掉COOKIE。         if (req.url ~ "^/[^?]+\..(jpeg|jpg|png|gif|bmp|tif|tiff|ico|wmf|js|css|ejs|swf|txt|zip|exe|html|htm)(\?.*|)$")  {                unset req.http.COOKIE;                set req.url = regsub (req.url,"\?.*$",""); #去掉Query Stings                if (req.http.Accept-Encoding){                        if (req.url ~ "\.(jpg|png|gif|jpeg|)") {                                remove 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{                                remove req.http.Accept-Encoding;                        }# 静态文件的压缩处理                }                return (lookup);        }        if (req.url ~ "\.(php|cgi)($|\?)"){                set req.backend = appservers;                return (pass); #是动态文件交给后端appservers处理        } else {                set req.backend = s1;                return (lookup); #静态文件交个s1处理        }}sub vcl_hash {        hash_data(req.url);        if (req.http.host) {        hash_data(req.http.host);        } else {        hash_data(server.ip);        }        if (req.http.Accept-Encoding ~ "gzip") {        hash_data("gzip");        }        elseif (req.http.Accept-Encoding ~ "deflate") {        hash_data("deflate");        }        return (hash); #对Accept-Encoding 进行hash}sub vcl_hit {        if (req.request == "PURGE") {                purge;                error 200 "Purged";        } # 请求是purge的 就返回200,成功。}sub vcl_miss{        if (req.request == "PURGE") {                purge;                error 404 "NOT in cache";        } #请求 是purge,返回404.}sub vcl_pass {        if (req.request == "PURGE") {                error 502 "PURGE on a passed object";        } #请求是purge,返回502.}sub vcl_fetch {        if (req.url ~ "^/$") {                unset beresp.http.set-COOKIE;        } #对应主页去除COOKIE。         if (beresp.status == 500 || beresp.status == 501 || beresp.status == 502 || beresp.status ==503 || beresp.status ==504) {                set beresp.saintmode = 20s;                return (restart);        } # 如果status是500,501,502,503,504,则启动saintmode。        if (beresp.http.Pragma ~ "no-cache" || beresp.http.Cache-Control ~ "no-cache" || beresp.http.Cache-Control ~ "private" ) {                return (hit_for_pass);        }        if (beresp.http.Set-COOKIE || beresp.ttl <= 0s || beresp.Vary == "*"  ) {                set beresp.ttl = 120s;                return (hit_for_pass);        }        if (req.request == "GET" && req.url ~ "\.(html|ejs|jpg|jpeg|png|xsl|xml|swf|ico|gif|css|js|htm)$") {                set beresp.ttl = 600s;        }        if (req.request == "GET" && req.url ~ "^/[^?]+\.(css|js|gif|jpg|jpeg|bmp|png|tiff|tif|ico|swf|exe|zip|bmp|wmf)(\?.*|)$" ) {                set beresp.ttl = 300s;        }        if (!req.backend.healthy){                set req.grace = 1m;        }        return (deliver);}sub vcl_deliver {        if (obj.hits > 0) {                set resp.http.X-Cache = "HIT from" + " " + server.ip;        }        else {                set resp.http.X-Cache = "miss";        }        return (deliver);}
[root@varnish1 ~]#  /etc/init.d/varnish start[root@varnish1 ~]# varnishlog    0 CLI          - Wr 200 19 PONG 1397943276 1.0    0 Backend_health - s1 Still healthy 4--X-RH 8 4 8 0.000689 0.001174 HTTP/1.1 200 OK    0 Backend_health - app1 Still healthy 4--X-RH 8 4 8 0.033177 0.010798 HTTP/1.1 200 OK    0 Backend_health - app2 Still healthy 4--X-RH 8 4 8 0.003488 0.003647 HTTP/1.1 200 OK    0 CLI          - Rd ping    0 CLI          - Wr 200 19 PONG 1397943279 1.0会看到 健康状态检查的。


检测varnish

第一次访问,查看x-cache 是miss的。第二次访问如下图

wKiom1Np7ZKzill_AAD8e9jWKm8182.jpg


wKioL1Np7bXToBFEAAEgy1ZySNo027.jpg

可以看到是 X-Cache:HIT from 192.168.1.151

使用varnishstat

wKiom1Np7pPi2SQ8AAE_hEUsQ0I345.jpg

命中率还是蛮高的哦


测试下purge:

wKiom1Np7vSimBoMAAE4td-8hu0249.jpg

wKiom1Np7xazURdpAAFCIZXbmeg830.jpg

wKioL1Np7xnCx3D1AAJNigMQ4go915.jpg


防盗链配置

在vcl_recv中添加:if (req.http.referer ~ "http://.*") {           if (!(req.http.referer ~ "http://.*\.baidu\.com" ||            req.http.referer ~ "http://.*\.google\.com.*" ||            req.http.referer ~ "http://.*\.sogou\.com" ||            req.http.referer ~ "http://.*\.soso\.com" ||            req.http.referer ~ "http://.*\.so\.com")) {            set req.http.host = "www.mytest.com";            set req.url = "/templets/default/images/logo.gif";        }            return (lookup);    }

不缓存大文件(比如大于10M)

sub vcl_recv {  if (req.http.x-pipe && req.restarts > 0) {    remove req.http.x-pipe;    return (pipe);  }}sub vcl_fetch {  if (beresp.http.Content-Length ~ "[0-9]{7,}") {    set req.http.x-pipe = "1";    return (restart);  }}

本文没有介绍DZ的安装,以及nginx的配置。nginx记录client的真实ip配置:

log_format     mylogformat     ' $http_x_forwarded_for- $remote_user [$time_local] '                                                  ' "$request" '                                                  ' "$http_referer" "$http_user_agent" ';  access_log /var/log/nginx/access3_log mylogformat;



本文出自 “小鱼儿” 博客,请务必保留此出处http://xiaoyuer3.blog.51cto.com/8622790/1408003


推荐阅读
  • 基于SSL的mysql服务器的主从架构实现说明:本文选用172.16.22.1作为主服务器,172.16.22.3作为从服务器从服务器的mysql软件版 ... [详细]
  • 本文介绍了5个基本Linux命令行工具的现代化替代品,包括du、top和ncdu。这些替代品在功能上进行了改进,提高了可用性,并且适用于现代化系统。其中,ncdu是du的替代品,它提供了与du类似的结果,但在一个基于curses的交互式界面中,重点关注占用磁盘空间较多的目录。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
  • 树莓派语音控制的配置方法和步骤
    本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
  • 近期,某用户在重启RAC一个节点的数据库实例时,发现启动速度非常慢。同时业务部门反馈连接RAC存活节点的业务也受影响。通过对日志的分析, ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了SpringCloudRibbon部分源码相关的知识,希望对你有一定的参考价值。1:ribbon是提供通过servi ... [详细]
  • Ansibleplaybook roles安装redis实例(学习笔记二十九)
    1、相关redis参数:2、templatesredis.conf配置相关参数:daemonizeyespidfilevarrunredis_{{red ... [详细]
  • 本文主要介绍关于linux文件描述符设置,centos7设置文件句柄数,centos7查看进程数的知识点,对【Linux之进程数和句柄数】和【linux句柄数含义】有兴趣的朋友可以看下由【东城绝神】投 ... [详细]
  • MySQL5.6.40在CentOS764下安装过程 ... [详细]
  • 本文介绍了在Mac上安装Xamarin并使用Windows上的VS开发iOS app的方法,包括所需的安装环境和软件,以及使用Xamarin.iOS进行开发的步骤。通过这种方法,即使没有Mac或者安装苹果系统,程序员们也能轻松开发iOS app。 ... [详细]
author-avatar
祗想抱著伱
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有