Linux 下Varnish 服务的部署

Linux 下Varnish 服务的部署

varnish 简介:

  • Varnish 是一款高性能、开源的反向代理服务器和缓存服务器。Varnish 使用内存缓存文件来减少响应时间和网络带宽消耗。这个项目是由挪威的一家报纸 Verdens Gang 的网络分支起始的,其架构设计和开发总监 Poul-Henning Kamp 是FreeBSD 核心的开发人员之一,最初项目的管理与基础设施及额外开发由挪威一家 Linux咨询公司 Linpro提供。
  • 说到varnish,squid 就不得不提及。squid 算得上是古老的缓存服务器。由于varnish先进的设计理念,性能要比squid高上许多 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。,varnish还可以通过端口进行管理,使用正则语句做到清除指定缓存的功能,这些squid都做不到。但是varnish在高并发的情况下,资源消耗较高,而且varnish服务进程一旦崩溃,重启,内存中的缓存数据将全部丢失。

varnish官方网站:https://www.varnish-cache.org/

1. Varnish 的设计结构

这里写图片描述
Varnish主要运行两个进程:Management进程和Child进程(也叫Cache进程)。如上图,

1.1 Management进程

  • Management进程主要实现应用新的配置、编译VCL、监控varnish、初始化varnish以及提供一个命令行接口等。Management进程会每隔几秒钟探测一下Child进程以判断其是否正常运行,如果在指定的时长内未得到Child进程的回应,Management将会重启此Child进程。

Management 管理接口:

  • CLI interface :命令行接口
  • Telnet interface :telnet接口
  • Web interface :Web管理接口

1.2 Child/Cache 进程

Child/Cache 进程包含多种类型的线程,常见的如:

  • Accept 线程:接收新的连接请求并响应
  • Worker 线程:child进程会为每个会话启动一个worker线程,因此,在高并发的场景中可能会出现数百个worker线程甚至更多;
  • Object Expiry 线程:从缓存中清理过期内容;
  • Commad line 线程 : 管理接口
  • Storage/hashing 线程 :缓存存储
  • Log/stats 线程:日志管理线程
  • Backend Communication 线程:管理后端主机线程
  • Varnish依赖“工作区(workspace)”以降低线程在申请或修改内存时出现竞争的可能性。在varnish内部有多种不同的工作区,其中最关键的当属用于管理会话数据的session工作区。

1.3 Varnish日志

  • 为了与系统的其它部分进行交互,Child进程使用了可以通过文件系统接口进行访问的共享内存日志(shared memory log),因此,如果某线程需要记录信息,其仅需要持有一个锁,而后向共享内存中的某内存区域写入数据,再释放持有的锁即可。而为了减少竞争,每个worker线程都使用了日志数据缓存。共享内存日志大小一般为90M,其分为两部分,前一部分为计数器,后半部分为客户端请求的数据。varnish提供了多个不同的工具如varnishlog、varnishncsa或varnishstat等来分析共享内存日志中的信息并能够以指定的方式进行显示。

1.4 VCL(Varnish Configuation Language)简介

  • Varnish Configuration Language (VCL)
    是 varnish配置缓存策略的工具,它是一种基于“域”(domain specific)的简单编程语言,它支持有限的算术运算和逻辑运算操作、允许使用正则表达式进行字符串匹配、允许用户使用set自定义变量、支持if判断语句,也有内置的函数和变量等。使用VCL编写的缓存策略通常保存至.vcl文件中,其需要编译成二进制的格式后才能由varnish调用。事实上,整个缓存策略就是由几个特定的子例程如vcl_recv、vcl_fetch等组成,它们分别在不同的位置(或时间)执行,如果没有事先为某个位置自定义子例程,varnish将会执行默认的定义。
  • VCL策略在启用前,会由management进程将其转换为C代码,而后再由gcc编译器将C代码编译成二进制程序。编译完成后,management负责将其连接至varnish实例,即child进程。正是由于编译工作在child进程之外完成,它避免了装载错误格式VCL的风险。因此,varnish修改配置的开销非常小,其可以同时保有几份尚在引用的旧版本配置,也能够让新的配置即刻生效。编译后的旧版本配置通常在varnish重启时才会被丢弃,如果需要手动清理,则可以使用varnishadm的vcl.discard命令完成。

2. Varish 的工作流程

Varnish处理HTTP请求的过程大致分为如下几个步骤:

  • Receive状态,也就是请求处理的入口状态,根据VCL规则判断该请求应该Pass或Pipe,还是进入Lookup(本地查询)。
  • Lookup状态,进入此状态后,会在hash表中查找数据,若找到,则进入Hit状态,否则进入miss状态。
  • Pass状态,在此状态下,会进入后端请求,即进入Fetch状态。
  • Fetch状态,在Fetch状态下,对请求进行后端获取,发送请求,获得数据,并进行本地存储。
  • Deliver状态, 将获取到的数据发送给客户端,然后完成本次请求。
    这里写图片描述
    • 图中椭圆形部分称为varnish的状态节点,又称为状态引擎,还有种叫法为varnish的内置函数。
    • 图中红色的线条:没有查询缓存/缓存中数据过期/缓存中没有数据 情况下的流程
    • 图中橙黄色的线条:直接将匹配数据通过内置函数vcl_pipe送往后台主机的流程
    • 图中绿色的线条:查询缓存数据命中且数据没有过期/经后台主机返回的数据经被缓存后返回给客户流程
    • 图中蓝色的线条:数据没有命中缓存向后台主机发出查询的流程
    • 图中黑色的线条:数据从后台主机返回给varnish缓存的流程

内置函数的参数作用

1. vcl_recv:用于接收和处理请求,请求到达并被成功接受后被调用。

四个主要用途:
  • 修改客户端请求数据减少缓存对象差异性:比如删除URL中的www.字符
  • 基于客户端数据选用缓存策略:不如不缓存POST请求,
  • 为web应用程序执行URL重写规则
  • 挑选合适的后端服务器
**经常使用的终止语句: **
 pass:绕过缓存,不从缓存中查询内容或不将内容存储至缓存
 pipe:不对客户端进行检查或做出任何操作,而是在客户端与后台服务间建立“管道”进行数据传输。
 lookup:在缓存中查找用户请求的对象
 error :格式:error code [reason] ,向客户端返回一个错误代码code 和 原因resion,该reason可自定义

2 vcl_pipe:将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,将不变的内容传递给客户端,直到这个链接被关闭。

**经常使用的终止语句:**
 pipe:说明见上
 error code [reason]:说明见上

3 vcl_hash: 在缓存中进行查询

4 vcl_hit:在缓存中找到请求的内容

**经常使用的终止语句:**
 deliver:将找到的内容发送给客户端,把控制权交个函数vcl_deliver
 error code [reason]:说明见上
 pass:将控制权交个vcl_pass函数处理,可能是缓存中数据过期所致

5 vcl_miss:当在缓存中没有找到匹配数据时被调用

**经常使用的结束语:**
 error code [reason]:说明见上
 pass:说明见上
 fetch:表示从后端获取的请求的内容,并将控制权交给VCL_fetch函数

6 vcl_pass:将请求直接传递给后端主机,后端主机将应答数据发送给客户端,而不执行缓存,每次都返回最新内容。

经常使用的结束语:
 error code [reason]:说明见上
 fetch:说明见上

7 vcl_fetch:向后端主机获取内容,通过判断将内容放入缓存,还是直接返回给客户端。

经常用的结束语:
 error code [reason]:说明见上
 deliver:将控制器交给vcl_deliver函数,将数据返回给客户端
 hit_no_pass:不缓存数据,直接返回给客户端

8 vcl_deliver函数:将缓存中找到的数据返回给客户端

**经常使用的结束语:**
 error code [reason]:说明见上
 deliver:将内容返回给客户端

3. Varnish 的基本配置

3.1 Varish 安装

准备安装包进行安装 执行命令进行安装
 [root@Server1 mnt]# cd /mnt/
 [root@Server1 mnt]# ls     # 此目录下有 varnish 所需安装包
 varnish-3.0.5-1.el6.x86_64.rpm  varnish-libs-3.0.5-1.el6.x86_64.rpm
 [root@Server1 mnt]# rpm -ivh varnish-*     # 通过 rpm 命令进行安装
执行如下: ![这里写图片描述](https://img-blog.csdn.net/20180728155657471?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0J1c3Rlcl9aUg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)

3.2 进行配置

**Varnish 的主要配置文件,及其说明**
 /etc/rc.d/init.d/varnish     # 启动脚本
 /etc/varnish/default.vcl     # 默认的vcl规则配置
 /etc/sysconfig/varnish       # 向varnish传递的参数
**配置文件说明** /etc/sysconfig/varnish
 NFILES=131072       --->打开的最大文件数,varnish 自动调整该值

 MEMLOCK=82000       --->内存中共享日志空间的大小
 NPROCS="unlimited"  --->单个用户运行的线程数
 RELOAD_VCL=1        --->设置为1 ,表示随着varnish的重启自动状态vcl策略配置文件
 VARNISH_VCL_CONF=/etc/varnish/default.vcl   --->默认vcl策略文件的位置
 VARNISH_LISTEN_PORT=80                      --->varnish监听的端口,默认为 6081
 VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1      --->varnish提供telnet管理端口监听的地址
 VARNISH_ADMIN_LISTEN_PORT=6082              --->varnish提供telnet管理端口监听的端口   VARNISH_SECRET_FILE=/etc/varnish/secret      --->varnish为管理端口提供的共享密钥文件 
 VARNISH_MIN_THREADS=50                      --->varnish启动时启动最少的线程数
 VARNISH_MAX_THREADS=1000                    --->varnish启动时启动最多的线程数   VARNISH_THREAD_TIMEOUT=120             --->varnish线程数的空闲时间,超过该时间自动销毁线程

 VARNISH_STORAGE_MEM=100M               --->使用内存为存储设备时使用的空间大小

 VARNISH_STORAGE="malloc,${VARNISH_STORAGE_MEM}"                               

                                  --->当varnish后端存储的配置,使用内存用来缓存数据,大小为100M

VARNISH_TTL=120   
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}"

对Varnish 进行配置

1. 编辑/etc/security/limits.conf
/etc/sysconfig/varnish 中规定了
  • NFILES=131072 # 打开的最大文件数
  • MEMLOCK=82000 # 内存中共享日志空间的大小
  • NPROCS=”unlimited” # 单个用户运行的线程数

将这些数据写入/etc/security/limits.conf 中
/etc/security/limits.conf 这个文件主要是用来限制用户对系统资源的使用,具体的使用方法 man 5 limits.conf,里面便给出了详细的用法

编辑如下:

 [root@Server1 mnt]# vim /etc/security/limits.conf
 内容如下:
 在文件最后添加:
 # End of file
 varnish     -    nofile   131072 
 varnish     -    memlock  82000
 varnish     -    nproc    unlimited

执行如下:
这里写图片描述

2. 编辑 /etc/sysconfig/varnish

将varnish监听的端口从6081 改为80

 [root@Server1 mnt]# vim /etc/sysconfig/varnish 
 编辑第 6665 # VARNISH_LISTEN_ADDRESS=
  66 VARNISH_LISTEN_PORT=80
  67 #
  68 # # Telnet admin interface listen address and port

执行如下:
这里写图片描述

2. 编辑 /etc/varnish/default.vcl

编辑此文件 添加 Apache 服务器,和进行 vcl 规则配置

 [root@Server1 mnt]# vim /etc/varnish/default.vcl
 编辑如下: 
   # 编辑后段服务器:
   7 backend default {
   8   .host = "172.25.21.2";    # 服务器 ip
   9   .port = "80";
  10 } 
  11 
   # 查看缓存命中情况 
  12 sub vcl_deliver {
  13 if (obj.hits > 0) {
  14         set resp.http.X-Cache = "HIT from test cache";
  15 }       
  16 else {
  17         set resp.http.X-Cache = "MISS from test cache";
  18 }       
  19 return (deliver);
  20 }

配置完成,重启服务,并加载varnish 规则

 [root@Server1 mnt]# /etc/init.d/varnish restart  # 重启服务
 [root@Server1 mnt]# /etc/init.d/varnish reload   # 重新加载规则

这里写图片描述

进行apacha 服务器的安装配置

执行命令进行httpd 服务的安装

 [root@Server2 ~]# yum install httpd - y  # httpd 服务安装
 [root@Server2 ~]# vim /var/www/html/index.html 
                 # 编辑默认发布文件

执行如下:
这里写图片描述
默认发布文件内容如下:
这里写图片描述

在服务端进行测试

修改服务端本地域名解析
 [root@foundation21 ~]# vim /etc/hosts
 编辑内容如下:
  172.25.21.1 www.test.com  nba.test.com    # 将 varnish 服务器的域名加上

这里写图片描述
在服务器端进通过浏览器访问 Apache 服务器
访问 Apache 服务器的 ip
这里写图片描述
访问 varnish 服务器的 ip
这里写图片描述
通过域名访问 varnish 服务器
这里写图片描述
我们的 varnish 服务器上是没有安装 Apache 服务的,而我们可以通过访问 varnish 服务而访问到 172.25.21.2 Apache 服务器的内容,这就是varnish 的作用之一,进行转发

我们可以通过 crul 命令来查看通过 varnish 对 HTTP 服务器内容的cache效果
执行:

 [root@foundation21 ~]# curl www.test.com -I  通过 varnish 服务器的域名进行访问
 HTTP/1.1 200 OK
 Server: Apache/2.2.15 (Red Hat)  # 服务器
 Last-Modified: Sat, 28 Jul 2018 08:04:44 GMT
 ETag: "9fa0b-20-5720aae603b9e"
 Content-Type: text/html; charset=UTF-8   # 文本类型
 Content-Length: 32          # 文本长度
 Accept-Ranges: bytes
 Date: Sat, 28 Jul 2018 08:59:26 GMT
 X-Varnish: 653942394    # varinsh 服务器
 Age: 0                  # 有效时间
 Via: 1.1 varnish        # 版本
 Connection: keep-alive  # 连接情况
 X-Cache: MISS from test cache  # cache情况
                                # 由于是第一次进行cache,需要从http 服务器端获取数据

第一次cache:
这里写图片描述
第二次cache:
这里写图片描述
为了查看varnish的缓存情况,我们可以将http服务器关闭,然后才缓存存活期内通过varnish 继续进行访问
关闭 httpd 服务器:
这里写图片描述
进行cache:
这里写图片描述
以此验证了varnish 的缓存效果

3.3 多个不同域名站点的后端服务器的配置

新建第二个 Apache 服务器

执行命令进行httpd 服务的安装

 [root@Server3 ~]# yum install httpd -y  # httpd 服务安装
 [root@Server3 ~]# vim /var/www/html/index.html 
                 # 编辑默认发布文件

执行如下:
这里写图片描述
默认发布文件内容如下:
这里写图片描述

在varnish 服务器进行配置

编辑 /etc/varnish/default.vcl

  [root@Server1 mnt]# vim /etc/varnish/default.vcl
  编辑内容如下:
  8 backend web1 {        # 第一个后端服务器
  9   .host = "172.25.21.2";
 10   .port = "80";
 11 }
 12 backend web2 {        # 第二个后端服务器
 13   .host = "172.25.21.3";
 14   .port = "80";
 15 }
 16 
 17 
 18 
 19 
 # 当访问 www.test.com 域名时从 web1 上取数据,访问 nba.test.com 域名时到 web2 取数据,
 # 访问其他页面报错。
 20 sub vcl_recv {
 21 if (req.http.host ~ "^(www.)?test.com") {
 22         set req.http.host = "www.test.com";
 23         set req.backend = web1;
 24         
 25 } elsif (req.http.host ~ "^nba.test.com") {
 26         set req.backend = web2;
 27 } else {
 28         error 404 "test cache";
 29 }       
 30 }

这里写图片描述
编辑完成重新加载varnish配置

 [root@Server1 mnt]# /etc/init.d/varnish restart
 [root@Server1 mnt]# /etc/init.d/varnish reload

这里写图片描述

在客户端进行测试

修改服务端本地域名解析
 [root@foundation21 ~]# vim /etc/hosts
 编辑内容如下:
  172.25.21.1 www.test.com  nba.test.com    # 将 varnish 服务器的域名加上

这里写图片描述

进行测试

 [root@foundation21 ~]# curl www.test.com    # 对服务器1进行访问
 <h1>www.test.com - server2<h1/>       # 默认发布文件内容
 [root@foundation21 ~]# curl nba.test.com    # 对服务器2进行访问
 nba.test.com                          # 默认发布文件内容
 [root@foundation21 ~]# curl sss.test.com    # 对未知服务器进行访问
 <html>                                   
 <head><title>302 Found</title></head>
 <body bgcolor="white">
 <center><h1>302 Found</h1></center>
 <hr><center>nginx/1.13.12</center>
 </body>
 </html>

这里写图片描述

3.4 健康检查与负载均衡

  • varnish可以对后端主机进行健康检测,动态进行移除或恢复后端主机调度列表
    • .probe:定义健康状态检测方法
    • .url:检测时请求的URL,默认为”/”;
    • .request:发出的具体请求;
    • .request =
    • “GET /.healthtest.html HTTP/1.1”
    • “Host: www.magedu.com”
    • “Connection: close”
    • .window:基于最近的多少次检查来判断其健康状态;
    • .threshhold:最近.window中定义的这么次检查中至有.threshhold定义的次数是成功的;
    • .interval:检测频度;
    • .timeout:超时时长;
    • .expected_response:期望的响应码,默认为200;

  • 负载均衡
    英文名称为Load Balance,其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。
  • varnish 的负载均衡可浅显的理解为,将一个服务器上的信息分摊到多个服务器上,防止一个服务器崩溃导致无法进行数据访问

具体操作如下:

在 varnish 端

配置 /etc/varnish/default.vcl

 [root@Server1 mnt]# vim /etc/varnish/default.vcl 
 编辑如下:
 probe healthcheck {
         .url = "/index.html";     # 哪个 url 需要 varnish 请求
         .interval = 5s;           # 检查的间隔时间
         .timeout = 1s;            # 等待多长时间探针超时
         .window = 5;              # 维持 5 个 sliding window 的结果
         .threshold = 3;           # 至少有三次 window 是成功的,就宣告bachend 健康
 }
 backend web1 {
   .host = "172.25.151.2";
   .port = "80";
   .probe = healthcheck;
 }

 backend web2 {
   .host = "172.25.151.3";
   .port = "80";
   .probe = healthcheck;
 }

 director test round-robin {   # 把多个后端聚合为一个组
 {  .backend = web1;  }
 {  .backend = web2;  }

 }
 sub vcl_recv {
 if (req.http.host ~ "^(www.)?test.com") {
         set req.http.host = "www.test.com";
         set req.backend = test;
         return(pass);   # 为了测试方便,不进行缓存
 }
 elsif (req.http.host ~ "^nba.test.com") {
         set req.backend = web2;
 }
 else {
         error 404 "test cache";
 }
 }

 编辑完成,进行重新加载
 [root@Server1 mnt]# /etc/init.d/varnish reload 

内容如下:
这里写图片描述
这里写图片描述
编辑完成,进行重新加载
这里写图片描述

在第二个http服务器进行配置

开启虚拟主机
编辑配置文件

 [root@Server3 ~]# vim /etc/httpd/conf/httpd.conf990 行  NameVirtualHost *:80  # 开启虚拟主机
 ......省略......
 <VirtualHost *:80>
    DocumentRoot /var/www/html
    ServerName nba.test.com
 </VirtualHost>

 <VirtualHost *:80>  
    DocumentRoot /www2
    ServerName www.test.com
 </VirtualHost>

这里写图片描述
这里写图片描述
建立虚拟主机的家目录与默认发布文件

 [root@Server3 ~]# mkdir /www2   # 创建目录
 [root@Server3 ~]# vim /www2/index.html   # 编辑默认发布文件
 [root@Server3 ~]# /etc/init.d/httpd restart  # 重启服务

这里写图片描述
默认发布目录内容
这里写图片描述

在客户端进行测试

 [root@foundation151 images]# curl www.test.com # 访问指定域名
 <h1>www.test.com - server2 <h1/>   # 默认发布目录
 [root@foundation151 images]# curl www.test.com
 www.test.com - server3

由于在配置文件中加上了 return(pass) 不进行缓存,所以会直接切换到不同的服务器,这样更直观了看出了负载均衡的作用,要是在一台服务器宕掉的情况下,还是可以访问到相应信息的

执行如下:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/Buster_ZR/article/details/81258791