分布式系统架构:技术栈详解与快速进阶
上QQ阅读APP看书,第一时间看更新

第5章
分布式架构Varnish

Varnish是一款高性能且开源的反向代理服务器和HTTP加速器,主要通过缓存来实现Web访问加速。它基于内存进行缓存,支持精确缓存时效,性能高效。其VCL配置管理比较灵活,支持后端服务器负载和健康检查,内部实现了负载均衡轮询调用服务器。

本章重点内容如下:

  • Varnish工作原理
  • Varnish源码编译安装
  • Varnish配置
  • Varnish核心指令
  • Varnish缓存
  • Varnish处理策略
  • Varnish健康检查
  • Varnish优化
  • Varnish高可用

5.1 Varnish工作原理

Varnish主要有两个进程,管理进程(Management)和子进程(Child)。其中,管理进程主要负责配置变更、编译VCL、监控运行、初始化、定期检查子进程(子进程宕机会重新开启);子进程包括Worker线程、Acceptor线程、Expiry线程,内部使用workspace工作区来减少多个线程间对内存的竞争。

Varnish工作模型图如图5-1所示。

098-1

图5-1 Varnish工作模型图

如图5-1所示,Varnish的工作流程如下。

1)Varnish的某个负责接收新HTTP连接的线程开始等待用户,如果有新的HTTP连接过来,它会负责接收,然后叫醒某个等待中的线程,并把具体的处理过程交给它。Worker线程读入HTTP请求的URI,查找已有的object。如果命中则直接返回并回复用户;如果没有命中,则需要从后端服务器中读取所请求的内容并存到缓存中,然后再回复。

2)分配缓存的过程:Varnish缓存对象时,默认会忽略体积过大的对象,因此会事先读取对象(object)的大小,经过默认配置的验证和筛选,保证其自身缓存策略的高效性。

为了读写高效性,会将筛选后合适的对象(object)压缩,压缩过程中会从现有的空闲存储结构体中查找,找到最合适大小的空闲存储块并将object分配给它。如果空闲块没有用完,就用多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据LRU机制,把最旧的object释放掉。

3)释放缓存的过程:有一个超时线程,检测缓存中所有object的生存期,如果超出设定的TTL(Time To Live)还没有被访问,就删除该object,并且释放相应的结构体及存储内存。注意释放时会检查该存储内存块前后空闲内存块,如果前后空闲内存和该释放内存是连续的,就将它们合并成一块更大的内存。

4)整个文件缓存的管理,没有考虑文件与内存的关系,实际上认为所有的object都在内存中,如果内存不足,系统会自动将其换到swap空间,而不需要Varnish程序去控制。

5)日志:为了与系统的其他部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。为了减少竞争,每个worker线程都使用了日志数据缓存。

6)共享内存日志大小一般为90MB,其分为两部分,前一部分为计数器,后一部分为客户端请求的数据。Varnish提供了多个不同的工具,如varnishlog、varnishncsa、varnishstat等,用以来分析共享内存日志中的信息并以指定的方式进行显示。

Varnish的优势如下:

  • Varnish支持更多的并发连接,因为Varnish的TCP连接比squid快;
  • Varnish访问速度快,因为其采用了Visual Page Cache技术,直接从内存中读取数据;
  • Varnish通过管理端口,使用正则表达式批量清除部分缓存;
  • Varnish量级轻且开源。

Varnish的缺点如下:

  • 进程一旦挂掉或重启,缓存的数据将从内存中完全释放;
  • 用多台Varnish实现负载均衡时,每次请求都会落到不同的Varnish服务器中,可能会造成URL请求穿透到后端。

5.2 Varnish源码编译安装

以Centos平台编译环境为例,安装Make并编译Varnish以及相关依赖插件的方法如代码清单5-1所示。

代码清单5-1 编译Varnish以及依赖插件

#需要安装编译gcc,已安装忽略
yum -y install gcc automake autoconf libtool make
yum install gcc gcc-c++

#安装pcre 正规表达式,已安装忽略
wget http:// www.programming.cn/pcre/pcre-8.36.tar.gz
tar -zxvf pcre-8.36.tar.gz
cd pcre-8.36
./configure --prefix=/usr/local/pcre/

make
make install

#安装libedit-dev, 已安装忽略
yum install libedit-dev*

#安装Varnish
wget -c http:// repo.varnish-cache.org/source/varnish-3.0.1.tar.gz
tar xzvf varnish-3.0.1.tar.gz
cd varnish-3.0.1
./configure --prefix=/usr/local/varnish PKG_CONFIG_PATH=/usr/lib/pkgconfig
make
make install

在Varnish的configure命令中,--prefix=path定义一个目录,也就是Varnish的安装目录,用于存放服务器上的文件。默认使用/usr/local/ varnish。

安装成功后 /usr/local/varnish目录如下:

bin     etc     include
lib     sbin    share      var

设置软连接ln -s /usr/local/varnish/sbin/varnishd /usr/sbin/,ln -s /usr/local/varnish/bin/* /usr/local/bin/,目的是让里面的内容暴露到外层,方便查看。

通过/usr/sbin -V查看varnish版本号,复制核心配置文件(default.vcl)到外层,如:cp /usr/local/varnish/share/doc/varnish/example.vcl /usr/local/varnish/default.vcl

启动varnish的方法如下:

进入cd /usr/sbin/
运行./varnished -f /usr/local/varnish/default.vcl -s malloc,32M -T 192.168.10.101:2000 -a 0.0.0.0:2222

其中,-s malloc表示存储类型和容量,-T 192.168.10.101:2000表示指定管理IP和端口,-a 0.0.0.0:2222表示对外界提供Web服务的IP和端口。

关闭varnish的方法如下:

进入cd /usr/sbin/
运行pkill varnished

通过Varnish代理运行的方法如下:

外部地址端口(http://192.168.10.101:2222/zachary/demo/showtime)被Varnish代理成内部地址端口(http://192.168.10.101:9021/zachary/demo/showtime),并可直接访问Tomcat页面。

Varnish提供了基于端口的管理方式,用户可以通过telnet方式登录到管理端口,对Varnish子进程进行启动、关闭、查看状态和清除缓存等操作,如代码清单5-2所示。

代码清单5-2 Varnish后台管理

[root@varnish ~]#telnet 192.168.10.101 2000
Trying 192.168.10.101...
Connected to localhost.localdomain (192.168.10.101).
Escape character is '^]'.
200 154
-----------------------------
Varnish HTTP accelerator CLI.
-----------------------------
Type 'help' for command list.
Type 'quit' to close CLI session.

#输入"help"即可得到如下帮助信息
help
200 377
help [command]
ping [timestamp]
auth response
quit
banner
status                          #显示服务运行状态
start                           #启动Varnish的子服务
stop                            #关闭Varnish的子服务
stats                           #显示服务的全部状态
#操作VCL配置文件的相关操作,如果要修改VCL文件
vcl.load <configname> <filename>
vcl.inline <configname> <quoted_VCLstring>
vcl.use <configname>            #载入指定的配置文件
vcl.discard <configname>        #丢弃指定的VCL配置文件
vcl.list                        #显示当前载入的VCL配置文件信息
vcl.show <configname>           #可以显示某个VCL文件的内容
param.show [-l] [<param>]       #用于显示程序的运行参数
param.set <param> <value>     #用于动态更改某个运行参数
purge.url <regexp>              #用来清除指定规则的URL缓存
purge <field> <operator> <arg>
purge.list                      #列出执行过的规则