对于一个站点,大家应该都比较清楚,资源大概就分为静态资源(js/css等),图片,文件,动态数据等。对于加快动态数据访问,通常是需要后端程序或数据结构作优化,才能比较明显地得到提升,并不是一个立竿见影的过程。但对于静态资源(js/css等),图片,文件等的访问,则可以通过一些缓存,压缩,合并等技术,就能得到比较明显的提升,本文将探讨下使用缓存来加快静态资源,图片等的访问,主要使用Varnish。
-
动静态资源分离
通常,对于具有一定规模的站点,是需要将动态资源(如后端服务提供的API数据接口)和静态资源(如图片,文件,js/css等)独立部署的,因为这些资源具有不同的访问属性,在运维层面也会有不同的策略,比如服务器配置,缓存策略等,下面是一个比较简易的部署架构:
-
对静态资源进行缓存
将动静态资源分离访问后,由于静态资源通常不会有内容更新,所以对它们进行缓存处理是再好不过,这也减少了不必要的资源解析,加载等,对于静态资源的缓存,也有许多比较成熟的解决方案,如Squid,Apache Traffic Server,Varnish,Nginx等,这里讲主要介绍ATS,Varnish,Nginx作资源缓存处理。ATS和Nginx基于文件缓存,而Varnish则基于内存缓存(收费的Varnish Plus应该支持文件)。
-
使用ATS,Nginx,Varnish作缓存处理
-
各缓存方案的特性对比
各缓存方案的一些特性对比:
-
使用ATS作缓存
-
安装
-
配置
具体各配置详情可见这里。
-
ATS中重要的几个组件
如下图,ATS中主要包含了
traffic_server,
traffic_manager,
traffic_cop组件:
traffic_server:Traffic Server的事务处理引擎,负责接收连接,处理协议请求,提供来自缓存或后端服务器的文件内容;
traffic_manager:Traffic Server的命令行和控制进程,负责运行,监控,重配置traffic_server进程,同时也负责代理自动配置端口,数据统计,集群管理,虚拟IP切换;
traffic_cop:监控traffic_server和traffic_manager的健康状态。
-
使用Nginx作缓存
使用nginx作缓存比较简单,只需使用proxy_cache指令,配置如下:
开启需要作缓存的server,如:
通常,可以在日志中输出缓存命中状态变量upstream_cache_status,以作缓存命中率统计:
必要的时候,有可能需要手动失效缓存,可通过proxy_cache_purge模块实现:
-
使用Varnish作缓存
Varnish与前两者不同,使用内存来缓存对象,即不会有磁盘I/O操作,也是最终选择的方案。可以看下其基本架构:
-
安装
-
配置
-
启动/关闭/重载
-
编写VCL
VCL(Varnish Configuration Language)作为Varnish核心的配置,作为一门小型的领域特性语言,其描述了Varnish应该如何处理请求,大致如下面的流程图:
常用的一些内置函数:
vcl_recv:用于接收和处理请求。当请求到达并成功接收后被调用,通过判断请求的数据来决定如何处理请求。例如如何响应、怎么响应、使用哪个后端服务器等;
vcl_pipe:此函数在进入pipe 模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容返回给客户端,直到这个连接被关闭;
vcl_pass:此函数在进入pass 模式时被调用,用于将请求直接传递至后端主机。后端主机在应答数据后将应答数据发送给客户端,但不进行任何缓存,在当前连接下每次都返回最新的内容;
vcl_hash:当您想把一个数据添加到 hash 上时,调用此函数;
vcl_hit:在执行lookup指令后,在缓存中找到请求的内容后将自动调用该函数;
vcl_miss:在执行lookup指令后,在缓存中没有找到请求的内容时自动调用该方法。此函数可用于判断是否需要从后端服务器获取内容;
vcl_fetch:在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端;
vcl_deliver:将在缓存中找到请求的内容发送给客户端前调用此方法;
vcl_error:出现错误时调用此函数。
下面是一份正在使用的配置:
-
Varnish Agent
Varnish Agent是一个微后台服务,用于远程控制和监控Varnish服务,使用比较简单:
varnish-agent内置的UI并不是很友好,可以使用Varnish Dashboard:
Varnish Dashboard配置样例:
访问http://${DASHBOARD_IP}:6085/html/后,即可在界面进行监控和操作:
-
总结
从上述可知,Nginx和ATS都是基于磁盘+内存的形式进行缓存,Varnish基于内存进行缓存。这就使得Varnish服务重启或宕机后,会导致所有缓存失效,重启后,则有可能造成短时后端访问高峰,Nginx和ATS则不会。
但不能单纯说是内存形式的缓存好,还是内存+磁盘形式好,若生产中,内存已经足够缓存频繁的静态资源,则使用内存形式即可,毕竟可以减少不必要的磁盘I/O管理。若生产中需要不时重启缓存服务,且不能接受短时访问高峰,则可以使用内存+磁盘形式。还有比较通用的方式,则是通过多级缓存的方式,如一级缓存使用Nginx/ATS,二级缓存使用Varnish:
在实际测试当中,当内存足够缓存频繁访问的资源时,三者性能上并没有明显的差距,当内存不足时,可想而知在高并发访问不同资源时,Nginx和ATS将带来频繁的磁盘I/O操作,势必影响性能。除了内存限制,比较明显就是带宽限制,应事先评估在静态资源大小与带宽限制下,能处理的最大并发请求数。
-
参考文献