目前,主流的前端缓存服务器已经大多从squid转向varnish。

国内研究varnish的大神很多了,比如南非蚂蚁就对此款软件进行了很多研究和测试,而且写了很多的配置和管理方面的文档,感兴趣的朋友可以去看下。

http://ixdba.blog.51cto.com/#

本人只是进行一个稍微立体化的介绍,供网友们参考。

首先,先简单做个varnish和squid的对比。 

 Varnish与Squid的对比  说到Varnish,不能不提Squid,Squid是一个高性能的代理缓存服务器,它和varnish之间有诸多的异同点,这里分析如下:  下面是他们之间的相同点:  (1)都是一个反向代理服务器。  (2)都是开源软件。  下面是它们的不同点,也是Varnish的优点:  (1)Varnish的稳定性很高,两者在完成相同负荷的工作时,Squid服务器发生故障的几率要高于Varnish,因为使用Squid要经常重启。  (2)Varnish访问速度更快,Varnish采用了“Visual Page Cache”技术,所有缓存数据都直接从内存读取,而squid是从硬盘读取,因而Varnish在访问速度方面会更快。  (3)Varnish可以支持更多的并发连接,因为Varnish的TCP连接释放要比Squid快。因而在高并发连接情况下可以支持更多TCP连接。  (4)Varnish可以通过管理端口,使用正则表达式批量的清除部分缓存,而Squid是做不到的。  (5) squid属于是单进程使用单核CPU,但Varnish是通过fork形式打开多进程来做处理,所以是合理的使用所有核来处理相应的请求。  当然,与传统的Squid相比,Varnish也是有缺点的,列举如下:  1) varnish进程一旦Hang、Crash或者重启,缓存数据都会从内存中完全释放,此时所有请求都会发送到后端服务器,在高并发情况下,会给后端服务器造成很大压力。  2) 在varnish使用中如果单个url的请求通过HA/F5(负载均衡)每次请求不同的varnish服务器中,被请求varnish服务器都会被穿透到后端,而且同样的请求会在多台服务器上缓存,也会造成varnish的缓存的资源浪费,也会造成性能下降。   解决方案:  1) 综上所述在访问量很大的情况下推荐使用varnish的内存缓存方式启动,而且后面需要跟多台squid服务器。主要为了防止前面的varnish服务、服务器被重启的情况下,前期肯定会有很多的穿透这样squid可以担当第二层CACHE,而且也弥补了varnish缓存在内存中重启都会释放的问题。  2) 这样的问题可以在负载均衡上做url哈希,让单个url请求固定请求到一台varnish服务器上,可以解决该问题。  注:上面的解决方法还需要全面的测试,没有经过证实。

一、varnish的诞生。

Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。

 

  

varnish

 

  Varnish 的作者Poul-Henning Kamp是FreeBSD的内核开发者之一,他认为现在的计算机比起1975年已经复杂许多。在1975年时,储存媒介只有两种:内存与硬盘。但现在计算机系统的内存除了主存外,还包括了CPU内的L1、L2,甚至有L3快取。硬盘上也有自己的快取装置,因此Squid Cache自行处理物件替换的架构不可能得知这些情况而做到最佳化,但操作系统可以得知这些情况,所以这部份的工作应该交给操作系统处理,这就是 Varnish cache设计架构。

 

  varnish项目是2006年发布的第一个版本0.9.距今已经四年多了,此文档之前也提过varnish还不稳定,那是2007年时候编写的,经过varnish开发团队和网友们的辛苦耕耘,现在的varnish已经很健壮。很多门户网站已经部署了varnish,并且反应都很好,甚至反应比squid还稳定,且效率更高,资源占用更少。相信在反向代理,web加速方面,varnish已经有足够能力代替squid。

二、varnish的特点。

(1)是基于内存缓存,重启后数据将消失。 (2)利用虚拟内存方式,io性能好。 (3)支持设置0~60秒内的精确缓存时间。 (4)VCL配置管理比较灵活。 (5)32位机器上缓存文件大小为最大2G。 (6)具有强大的管理功能,例如top,stat,admin,list等。 (7)状态机设计巧妙,结构清晰。 (8)利用二叉堆管理缓存文件,达到积极删除目的。

三、varnish的工作流程

1、进程之间通信

 varnish启动或有2个进程 master(management)进程和child(worker)进程。master读入存储配置命令,进行初始化,然后fork,监控child。child则分配线程进行cache工作,child还会做管理线程和生成很多worker线程。

child进程主线程初始化过程中,将存储大文件整个加载到内存中,如果该文件超出系统的虚拟内存,则会减少原来配置mmap大小,然后继续加载,这时候创建并初始化空闲存储结构体,放在存储管理的struct中,等待分配。

接着varnish某个负责接口新http连接的线程开始等待用户,如果有新的http连接,但是这个线程只负责接收,然后唤醒等待线程池中的work线程,进行请求处理。

worker线程读入uri后,将会查找已有的object,命中直接返回,没有命中,则会从后端服务器中取出来,放到缓存中。如果缓存已满,会根据LRU算法,释放旧的object。对于释放缓存,有一个超时线程会检测缓存中所有object的生命周期,如果缓存过期(ttl),则删除,释放相应的存储内存。

 

2、配置文件各结构之间通信

 

四、大神们眼中的varnish ---张宴
  1、Varnish采用了“Visual Page Cache”技术,在内存的利用上,Varnish比Squid具有优势,它避免了Squid频繁在内存、磁盘中交换文件,性能要比Squid高。
  2、Varnish的稳定性还不错,我管理的一台图片服务器运行Varnish已经有一个月,没有发生过故障,而进行相同工作的Squid服务器就倒过几次。
  3、通过Varnish管理端口,可以使用正则表达式快速、批量地清除部分缓存,这一点是Squid不能具备的。

  点击在新窗口中浏览此图片

 五、varnish性能测试。

1、varnish的加速测试

服务器参数:系统centos 5 32位,单核,Intel(R) Xeon(R) CPU L5630 @ 2.13GHz,1G内存 没有经过varnish缓存的测试结果: 负载40.44 Concurrency Level: 100 Time taken for tests: 305.766 seconds Complete requests: 1000 Failed requests: 1 (Connect: 0, Receive: 0, Length: 1, Exceptions: 0) Write errors: 0 Non-2xx responses: 1 Total transferred: 19746015 bytes HTML transferred: 19521638 bytes Requests per second: 3.27 [#/sec] (mean) Time per request: 30576.620 [ms] (mean) Time per request: 305.766 [ms] (mean, across all concurrent requests) Transfer rate: 63.07 [Kbytes/sec] received 开启了varnish前端缓存的 负载0.05  Concurrency Level: 100 Time taken for tests: 12.720 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 20086736 bytes HTML transferred: 19821261 bytes Requests per second: 78.62 [#/sec] (mean) Time per request: 1271.991 [ms] (mean) Time per request: 12.720 [ms] (mean, across all concurrent requests) Transfer rate: 1542.15 [Kbytes/sec] received

但从数据可以看出有varnish比没有的加速20-30倍。

2、varnish VS squid对比测试

 da01~/siege-2.69# siege -b -c 500 -t 60s http://www.aipai.com:8080/about/map.html  ** SIEGE 2.69 ** Preparing 500 concurrent users for battle. The server is now under siege... Lifting the server siege...      done.  Transactions:                 653211 hits   Availability:                 100.00 %           Elapsed time:                  59.35 secs Data transferred:            1238.43 MB Response time:                  0.05 secs               //平均相应时间 Transaction rate:           11006.08 trans/sec   //平均每秒处理速度,请求/s Throughput:                    20.87 MB/sec          //网络吞吐量 Concurrency:                  498.86                         //最高并发数 Successful transactions:      653212                         //成功处理数 Failed transactions:               0                         //失败处理数 Longest transaction:            3.01                         //最长的请求处理时间 Shortest transaction:           0.00 对于测试结果详细的说明,有兴趣的朋友请查阅siege的文档,比较关键的几个数据上面已经标注了。 测试1: 目标URL:http://www.aipai.com:8080/about/map.html,测试小文件请求,文件大小:6221 byte 并发 10 并发 100 并发 500 并发 1000 squid 2.6 STABLE23 8207 11211 11016 10451 squid 2.7 STABLE9 8261 11409 11006 10002 squid 3.0 STABLE25 8524 9762 8138 8768 squid 3.1.11 6421 6832 5990 5834 varnish 2.1.5 10875 10251 11459 11412 PS:siege使用超过1000个并发会报错。 测试2: 目标URL:http://www.aipai.com:8080/c7/Pjg_KScqImgnaiYs.html,测试我们网站典型的播放页请求,文件大小:75356 byte 并发 10 并发 100 并发 500 并发 1000 squid 2.6 STABLE23 4554 6382 6625 6696(4 failed ) squid 2.7 STABLE9 4164 6234 6565 6588 squid 3.0 STABLE25 4366 5315 5190 5153 squid 3.1.11 3697 4217 4357 4075 varnish 2.1.5 6618 6781 6775 5714 测试1,测试2总结: 测试1,测试2都是对一个URL进行强压,主要测试MEM_HIT时候软件的处理能力。 1、squid 2.6在squid组中基本是最快的,在测试2并发1000的时候开始不太稳定,有4个Connection timed out。 2、squid 2.7的成绩和2.6在一个水平线,略逊一点。 3、squid 从3.0开始用c++全部重写,目前看来与2.7/2.6性能差距还很明显,3.1从性能上来看比3.0还差(squid哥,不能为了功能损失太多的性能啊)。 4、varnish在大多数测试上处于领先,有些项目差一些(varnish的测试结果不是很稳定,有一些摆幅)。varnish性能比squid强一些,不过远没有达到某些文章宣称的是squid的10倍。 测试3: 进一步模拟生产环境,从实际运行的squid access log中截取了5万个url来测试。 每次测试延长到2分钟。 并发 10 并发 100 并发 500 并发 1000 squid 2.6 STABLE23 2839 5485 6722 6604 squid 2.7 STABLE9 2981 5215 6789 6742 squid 3.0 STABLE25 2863 4294 4345 3859 squid 3.1.11 2682 3763 3402 3262 varnish 2.1.5 NA NA NA NA   4934   注:varnish的测试有一点问题,siege会很快报出结果(并没有到设定的2分钟),查看varnish的log还在不断的有请求进来,这个测试中siege的结果不能使用。 报错: ** SIEGE 2.69 ** Preparing 100 concurrent users for battle. The server is now under siege...    done. siege aborted due to excessive socket failure; you can change the failure threshold in $HOME/.siegerc Transactions:                 181336 hits Availability:                  99.43 %   测试3总结: 1、由于varnish的成绩有问题,这里就只是squid各版本的比拼了。这个测试比之前的测试1,2更有意义一点,因为能更真实的模拟生产环境(url列表就是从生产环境中截取了一段)。 2、在这个测试中squid 2.7表现的很出色,有3个环节的分数都比之前测试1,测试2中表现更好的squid 2.6高。 3、再验证测试的时候发现,这组测试结果变化较大。拿并发100时squid 2.7的数据来说,结果从3800到5600都有。分析原因可能是因为这里访问的是生产环境URL列表,需要去后端拿各种页面,有不少页面还需要请求数据库(后端和数据库这个时候都还在跑生产环境,并不是空闲的,当跑测试的时候数据库load明显升高),后端和数据库的繁忙程度会导致测试结果有一定偏差。 4、有偏差也能看出一个大致趋势,和测试1,2的结论其实差不多:2.6/2.7的性能接近,3.0差一些,3.1最差。

3、varnish VS nginx 对比测试

nginx机器配置:  CPU:     E7500  @ 2.93GHz (双核)  内存:4G  varnish机器配置:  CPU:     E3300  @ 2.50GHz (双核)  内存:2G  测试脚本执行机器配置:  CPU:     AMD Phenom(tm) II X4 925 Processor  内存:2G 2:测试准备工作  2.1:安装siege 使用压力测试工具siege(http://www.joedog.org/index/siege-home) 来验证。可以根据路径来并发重复压力测试。安装方式:  下载:wgetftp://sid.joedog.org/pub/siege/siege-latest.tar.gz  安装:  #./configure  #make && make install [root@localhost test] siege -c 100 -r 100 -f varnish_url.txt [root@localhost test] siege -c 100 -r 100 -f nginx_url.txt 参数说明:  -c 100 并发100个用户  -r 100 重复循环100次  -f varnish_url.txt 任务列表:URL列表 2.2:构造URL  构造了536个url测试,其中1个是错误的url。 到测试机器上, [root@localhost test] cd /data/htdocs/resources/web [root@localhost test] find . -name "*.jpg" -print > varnish_url.txt 2.3:开启nginx页面缓存方法  开启nginx的缓存图片的方法,在nginx的conf中添加: location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|ico)$ {     expires      30d;     access_log   off; } 3:运行后测试结果:  3.1.1:nginx开启页面缓存的情况 Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  65.83 secs  Data transferred:             260.83 MB  Response time:                  0.01 secs  Transaction rate:            151.91 trans/sec  Throughput:                     3.96 MB/sec  Concurrency:                    2.06  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            3.03  Shortest transaction:           0.00  3.1.2:nginx不开启页面缓存的情况  Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  63.90 secs  Data transferred:             266.10 MB  Response time:                  0.01 secs  Transaction rate:            156.49 trans/sec  Throughput:                     4.16 MB/sec  Concurrency:                    2.18  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            0.35  Shortest transaction:           0.00  3.1.3:nginx开启页面缓存第二次测试的情况  Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  63.05 secs  Data transferred:             266.10 MB  Response time:                  0.01 secs  Transaction rate:            158.60 trans/sec  Throughput:                     4.22 MB/sec  Concurrency:                    2.06  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            0.34  Shortest transaction:           0.00  3.2.1:varnish清空缓存第一次测试情况  Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  62.87 secs  Data transferred:             266.10 MB  Response time:                  0.01 secs  Transaction rate:            159.06 trans/sec  Throughput:                     4.23 MB/sec  Concurrency:                    1.95  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            0.37  Shortest transaction:           0.00  3.2.2:varnish有缓存测试  Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  61.91 secs  Data transferred:             266.10 MB  Response time:                  0.01 secs  Transaction rate:            161.52 trans/sec  Throughput:                     4.30 MB/sec  Concurrency:                    1.78  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            0.34  Shortest transaction:           0.00  3.2.3:varnish负责均衡性能  Transactions:                  10000 hits  Availability:                 100.00 %  Elapsed time:                  59.75 secs  Data transferred:             266.10 MB  Response time:                  0.01 secs  Transaction rate:            167.36 trans/sec  Throughput:                     4.45 MB/sec  Concurrency:                    1.98  Successful transactions:        9900  Failed transactions:               0  Longest transaction:            3.01  Shortest transaction:           0.00 4:结论  在varnish机器性能较差的情况下,在高并发情况下,能够跑出比nginx更好的性能。 线上是读取了单台图片服务器,使用varnish能够解决图片服务负责均衡的问题,减少了nginx对内存的存储双份造成浪费的问题。 有varnish负载均衡,单台img服务器故障时能让服务继续。当然varnish故障了,需要有备份服务器。

4、varnish两种存储模式测试

 硬件环境

PowerEdge R610 CPU  Intel(R) Xeon(R) CPU           E5620  @ 2.40GHz 内存  12G 硬盘  单盘raid0 (150G * 3块) 软件环境centos5.4  Kernel2.6.18-164.el5 测试软件版本:varnishd 2.1.5

 测试工具

消减网络频宽/吞吐量,在相同服务器上生成负载,使用Apache Bench工具(修改后的ab)模仿线上访问,将百万的url请求以顺序的方式读取,然后用2台服务器启动多个ab一次产生的请求500个请求循环N次请求到varnish服务器。

 测试前设置:

1)先将测试机内核可以同时打开的文件描述符的最大值设置到65535。(ulimit -HSn 65532)

2)强制内核不要使用SWAP分区。(echo 0 > /proc/sys/vm/swappiness )

Varnish的Storage方式

1)malloc 通过malloc获取内存。

2) Mmap file 创建大文件,通过二分法分段映射成1G以内的大块。

综合测试

1) Malloc 方式

启动命令:

/opt/varnish-2.1.5/sbin/varnishd -u www -g www -f /opt/varnish-2.1.5/etc/varnish/varnish.vcl -s malloc,2G -w 10,5000,10 -T 192.168.1.100:3500

测试详细数据:

varnish压测类型

varnish压测数据 His/s 1.8W/s 压测文件大小 15K(平均) CPU状态(idle%) 60% 两块网卡流量 200M(打满) 磁盘的繁忙程度 0% 命中率 98%

 2) Mmap file方式

启动命令:

/opt/varnish-2.1.5/sbin/varnishd -u www -g www -f /opt/varnish-2.1.5/etc/varnish/varnish_test.vcl -s file,/data0/varnish_cache/cache_data.txt,2G -w 10,5000,10 -T 192.168.1.100:3500

测试详细数据:

varnish压测类型

varnish压测数据 His/s 1.8W/s 压测文件大小 15K(平均) CPU状态(idle%) 50% 两块网卡流量 200M(打满) 磁盘的繁忙程度 100%(SDA) 命中率 98%

 参数详解:

-f  指定配置文件

 -s  选项用来确定 varnish 使用的存储类型和存储容量,我使用的是 malloc 类型(malloc  是一个 C  函数,用于分配内存空间),  1G  定义多少内存被 malloced,1G  =1gigabyte。

 -w  min[,max[,timeout]]指定线程最小和最大空闲时间。这是一个设置thread_pool_min和thread_pool_max、thread_pool_timeout的捷径。如果只有一个值被指定,那么thread_pool_min和thread_pool_max都是用这个值。Thread_poll_timeout会失效。

 -T Varnish 有一个基于文本的管理接口,启动它的话可以在不停止 varnish 的情况下来 管理 varnish。

 -t      ttl     指定最小的TTL给cache中的内容。这是一个捷径设置default_ttl run-time 选项。

综合分析

从varnish服务器的总体上来看,在每秒并发1.8W左右的情况下,采用缓存方式以Mmap file和Malloc方式都会导致两块网卡跑满,但以Mmap file的缓存方式启动I/O也会形成瓶颈,原因主要是varnish缓存的数据先会刷到磁盘上,然后在一次行读到内存中,这在访问量大的时候同时也会对I/O造成很大的压力。Malloc缓存方式虽然对I/O没有压力,因所有缓存数据都写到内存中。

 

六、varnish的前进步伐。

目前varnish没有比较好的管理界面和汉化功能,但相信今后大神们一定会完善起来。而且目前主流的网上文档是基于2.0的,而现在官方已经出到3.0的版本。

所以好多配置文档的语法已经更新。在这里我就给出一个简单的3.0的配置文档供大家参考。

backend webserver {   .host = "10.10.1.132";   .port = "80"; }   sub vcl_recv {      if (req.restarts == 0) {     if (req.http.x-forwarded-for) {         set reqreq.http.X-Forwarded-For =         req.http.X-Forwarded-For + ", " + client.ip;     } else {         set req.http.X-Forwarded-For = client.ip;     }      }      if (req.request != "GET" &&        req.request != "HEAD" &&        req.request != "PUT" &&        req.request != "POST" &&        req.request != "TRACE" &&        req.request != "OPTIONS" &&        req.request != "DELETE") {          /* Non-RFC2616 or CONNECT which is weird. */          return (pipe);      }    if (req.request != "GET" && req.request != "HEAD") {            return (pass);         }          if (req.http.host ~ "^(.*).123.com" || req.http.host ~ "^(.*).123.com") {            set req.backend = webserver;         }          if (req.url ~ "\.(jsp|do)($|\?)") {            return (pass);         } else {         return (lookup);         } }     sub vcl_pipe {     return (pipe); }   sub vcl_pass {     return (pass); }    sub vcl_hash {      hash_data(req.url);      if (req.http.host) {          hash_data(req.http.host);      } else {          hash_data(server.ip);      }      return (hash);  }  sub vcl_hit {     return (deliver); }   sub vcl_miss {     return (fetch); }    sub vcl_fetch {      if (beresp.ttl <= 0s ||          beresp.http.Set-Cookie ||          beresp.http.Vary == "*") {         /*          * Mark as "Hit-For-Pass" for the next 2 minutes          */         set beresp.ttl = 120 s;         return (hit_for_pass);      }  if (req.request == "GET" && req.url ~ "\.(png|xsl|xml|pdf|ppt|doc|docx|chm|rar|zip|bmp|jpeg|swf|ico|mp3|mp4|rmvb|ogg|mov|avi|wmv|swf|txt|png|gif|jpg|css|js|html|htm)$") {        set beresp.ttl = 600s;      if (req.url ~ "\.(png|gif|jpg)$") {          unset beresp.http.set-cookie;          set beresp.ttl = 1h;      }          return (deliver);  }   }  sub vcl_deliver {     if (obj.hits > 0) {        set resp.http.X-Cache = "HIT from 123.com";     } else {       set resp.http.X-Cache = "MISS from 123.com";     }     return (deliver); }

 PS:varnish确实是一个很棒的前端缓存服务器的新秀,就像nginx的出现一样,随着互联网的发展,期待有越来越多优秀作品的呈现,当然也少不了我们的研究和推动。

喜欢技术的朋友,也可以加QQ群进行交流,群里大神多,我们共同努力,推动开源。

QQ群:89342115

linux运维培训 http://www.magedu.com