linux运维—varnish模拟CDN网络

一 、CDN

什么是CDN

CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。

基本原理

CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。

基本思路

基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的环节,使内容传输的更快、更稳定。通过放置节点服务器在现有的互联网基础之上形成一个智能虚拟网络。CDN系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度。

网络服务模式

内容分发网络(CDN)是一种新型网络构建方式,代表了一种基于质量与秩序的网络服务模式。包括分布式存储、负载均衡、网络请求的重定向和内容管理4个要件。

内容管理和全局的网络流量管理(Traffic Management)是CDN的核心所在。通过用户就近性和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务。

内容服务基于缓存服务器,也称作代理缓存(Surrogate),它位于网络的边缘,距用户仅有"一跳"(Single Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于CDN服务提供商的数据中心)的一个透明镜像。这样的架构使得CDN服务提供商能够代表他们客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间有任何延迟的。

二、varnish

Varnish是高性能开源的反向代理服务器和HTTP缓存服务器,Varnish的功能与Squid服务器相似,都可以用来做HTTP缓存。

Squid是从硬盘读取缓存的数据,而Varnish把数据存放在内存中,直接从读取内存,避免了频繁在内存、磁盘中交换文件,所以Varnish要相对更高效,但也有缺点,内存中的缓存在服务器重启后会丢失

Varnish 如何工作

varnish启动时会产生2个进程,一个由root开启(主进程),一个由varnish开启(子进程);主进程 fork 子进程,主进程等待子进程的信号,子进程退出后,主进程重新启动子进程。

子进程生成若干线程,具体对客户的请求进行处理:

  • Accept 线程:监听端口,接受连接;接受连接后组成 session 结构,查看是否有空闲线程,若有则分配给其处理,若无,则检查等待队列 overflow 的大小,若过大,则抛弃请求,否则加入 overflow 队列。
  • Work 线程:从对列上摘除请求,对请求进行处理,直到完成,然后处理下一个请求。子进程会为每一个用户请求(如果需要处理),启一个worker线程,所以它单线程,单响应的;即是每一个请求用一个独立的线程响应的
  • Epoll 线程: 一个请求处理称作一个 session,在 session 周期内,处理完请求后,会交给Epoll 处理,监听是否还有事件发生。
  • Expire 线程:对于缓存的对象,根据过期时间,组织成二叉堆,该线程周期检查该堆的根,处理过期的文件
初始化过程

Varnish 的master进程负责启动工作,master进程读取配置文件,根据指定的空间大小(例如管理员分配了2G内存)来创建存储空间,创建并管理child进程

child进程来处理后续任务,它会分配一些线程来执行不同的工作,例如:

  • 接受http请求
  • 为缓存对象分配存储空间
  • 清除过期缓存对象
  • 释放空间 碎片整理

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

分配缓存过程
它根据所读到object的大小,创建相应大小的缓存文件。为了读写方便,程序会把每个object的大小变为最接近其大小的内存页面倍数。然后从现有的空闲存储结构体中查找,找到最合适的大小的空闲存储块,分配给它。如果空闲块没有用完,就把多余的内存另外组成一个空闲存储块,挂到管理结构体上。如果缓存已满,就根据LRU机制,把最旧的object释放掉

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

varnish 配置语言-VCL

大部分其他的系统使用配置指令,让您打开或者关闭一些开关。 Varnish 使用区域配置语言,这种语言叫做“VCL”(varnish configuration language)。

VCL 语言是 varnish (HTTP 加速器)的一种限定域语言,目的在于规定请求的处理
和内容的缓存策略。

当一个新的配置文件被加载,varnish 管理进程把 vcl 转换成 c 代码,然后编译成动
态共享库连接到服务器进程。

安装 varnish 的系统需要 C 编译器,VCL 编译需要 C 编译器来完成。系统的 C 编译器把 VCL 编译成动态共享库,然后供varnish 使用。所以没有 C 编译器,varnish 不能运行。

在 VCL 中,有 3 个重要的数据结构:

  • request 从客户端进来
  • responses 从后端服务器过来
  • object 存储在 cache 中

VCL 支持以下运算符:

符号运算
=赋值运算符
==对比
~匹配,在 ACL 中和正则表达式中都可以用
!否定
&&逻辑与
||逻辑或

VCL 文件被分为多个子程序,不同的子程序在不同的时间里执行,比如一个子程序在接到请求时执行,另一个子程序在接收到后端服务器传送的文件时执行。

varnish 将在不同阶段执行它的子程序代码,因为它的代码是一行一行执行的,不存在优先级问题。随时可以调用这个子程序中的功能并且当他执行完成后就退出。

子程序在 VCL 中没有参数,也没有返回值。调用一个子程序,使用子程序的关键字名字:

这里有很多子程序和 varnish 的工作流程相关。这些子程序会检查和操作 http 头文件和各种各样的请求。决定哪个哪些请求被使用。

1 vcl_recv
在请求开始的时候被调用,当一个完整的请求被接受到,并被解析,它的作用就是决定是否给这个请求提供服务,怎么服务,如果服务,哪个后端会被选取。

vcl_recv 子程序以下面的关键字结束:

  • error code [reason] \返回规定的代码给客户端,并终止请求。
  • pass \转换到 pass 模式,控制权会传递给 vcl_pass。
  • pipe \转换到 pipe 模式,控制权会传递给 vcl_pipe。
  • lookup \在 cache 中查找请求目标,控制权最终会传递给 vcl_hit 或者vcl_miss,取决于目标是否在 cache 中

2 vcl_pass
请求进入 pass 模式的时候被调用,在这个模式,请求会被 passed 到后端服务器,后端服务器的应答会被 passed 给客户端,但是不会被缓存。相同客户端的随后的请求正常处理。

3 vcl_pipe
请求进入 pipe 模式的时候被调用,在这个模式,请求会被 passed 到后端服务器,在连接关闭前,无论是这个客户端还是对应的后端服务器的数据,都会进入 pass 模式。

4 vcl_hit
当一个请求从 cache 中命中需要的内容,vcl_hit 子程序以下面关键字结束:

  • error code [reason] \返回规定的代码给客户端,并终止请求。
  • pass\继续进入 pass 模式,控制权转交 vcl_pass 子程序。
  • deliver \提交命中的目标给客户端,控制权转交 vcl_deliver 子程序

5 vcl_miss
当需要的内容没有在缓存中命中的时候被调用,决定是否尝试到后端服务器查找目标,从哪个后端服务器查找目标?vcl_miss 子程序以下面的关键字结束:

  • error code [reason] \返回规定的代码给客户端,并终止请求
  • pass \进入 pass 模式,控制权转交给 vcl_pass
  • fetch \从后端服务器获得请求目标,控制权转交给 vcl_fetch

6 vcl_fetch
目标成功从后端服务器中获取的时候被调用,vcl_fetch 子程序以下面的关键字结束:

  • error code [reason] \返回规定的代码给客户端,并终止请求
  • pass \进入 pass 模式,控制权转交给 vcl_pass
  • deliver \可能把找到的目标插入缓存中,然后发送给客户端,控制权转交给vcl_deliver

7 vcl_deliver
当一个没有被 cached 内容交付给客户端的时候被调用,vcl_deliver 子程序以下面关键字结束:

  • error code [reason] \返回规定的代码给客户端,并终止请求。
  • pass \进入 pass 模式,控制权转交给 vcl_pass
  • deliver \交付目标给客户端

安装varnish 模拟CDN

1 环境:三台主机:为了实验方便,全部关闭防火墙,selinux设置为disabled
代理服务器:172.25.47.110
后端资源服务器:172.25.47.120
客户端物理主机:172.25.47.130

2 代理服务器安装配置varnish
1 安装包:
varnish-4.0.5-1.el7.x86_64.rpm
varnish-libs-4.0.5-1.el7.x86_64.rpm
jemalloc-3.6.0-1.el7.x86_64.rpm

[root@server1 varnish]# yum install -y varnish-4.0.5-1.el7.x86_64.rpm \
varnish-libs-4.0.5-1.el7.x86_64.rpm jemalloc-3.6.0-1.el7.x86_64.rpm  # 对安装包以及其依赖进行安装
[root@server1 varnish]# rpm -qc varnish-4.0.5-1.el7.x86_64   # 查看varnish在系统中生成的文件
 /etc/logrotate.d/varnish
 /etc/varnish/default.vcl    # varnish配置文件
 /etc/varnish/varnish.params

2 查看varnish的服务文件

vim /usr/lib/systemd/system/varnish.service

查看varnish服务中设定的最大开启文件数量以及锁定的内存大小:
在这里插入图片描述
Varnish打开的最大文件数限制为131072
Varnish锁定的共享内存大小为82M

3 查看本机系统最大文件访问数量,修改虚拟机内存大小

sysctl -a | grep file   # 查看本机系统最大文件访问数量

在这里插入图片描述
由于系统最大文件访问数量不满足varnish要求,所以此时更改虚拟机配置,增加内存至2048M
在这里插入图片描述
修改后重新查看系统最大当我呢文件数以及结构可以满足varnish的需要。
在这里插入图片描述
4 全局临时更改共享内存及最大文件数

[root@server1 varnish]# ulimit -n 131072  ##临时更改更改最大文件数
[root@server1 varnish]# ulimit -l 82  ##临时更改更改最大共享内存
[root@server1 varnish]# ulimit -a # 查看用户限制
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 3885
max locked memory       (kbytes, -l) 82  ##最大共享内存更改成功
max memory size         (kbytes, -m) unlimited
open files                      (-n) 131072  ##最大文件数更改成功
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 3885
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

5 编辑varnish用户的限制文件(与varnish配置文件中限制相对应)

vim /etc/security/limits.conf  # 编辑该文件,将最大文件访问数以及锁定的内存大小写入文件最后

在这里插入图片描述
6 修改varnish服务端口:

root@server1 ~]# vim /etc/varnish/varnish.params  ##在该文件中编辑更改端口为80

在这里插入图片描述
7 varnish主配置文件中指定后端服务器:

vim /etc/varnish/default.vcl  # 编辑varnish主配置文件

在这里插入图片描述

systemctl restart varnish  # 重新启动varnish服务

3 设置后端服务器
后端资源服务器,安装http服务,在共享目录中编写共享文件。

[root@server2 ~]# yum install httpd -y
[root@server2 ~]# systemctl start httpd
[root@server2 ~]# systemctl enable httpd
[root@server2 html]# echo hello toto > /var/www/html/index.html
[root@server2 html]# systemctl restart httpd
[root@server2 html]# cat index.html
hello toto

4 测试:使用物理主机直接访问代理服务器,可以得到资源服务器中的内容:

[root@toto3 ~]# curl 172.25.47.110
hello toto
[root@toto3 ~]# 

二、Varnish缓存命中情况
作为varnish代理端,在配置文件中添加了后端服务器的ip及端口,在访问代理端的时候实际是在访问后端服务器,则第一次访问会产生缓存,下一次访问的时侯则由缓存服务器直接响应客户端需求,减少延时。

修改配置文件,在缓存数据时发送信息给客户端(查看缓存命中情况),根据数据是来自后端服务器还是来自缓存的内容,返回不同的消息给客户端主机。

vim /etc/varnish/default.vcl  #编辑配置文件

vcl_deliver
在缓存数据将要发送到客户端时调用的子进程。
在这里插入图片描述

systemctl restart varnish  # 重新启动varnish服务

在代理服务器上对varnish缓存进行清理:

varnishadm ban req.url "~" /    # 清理所有的缓存
varnishadm ban req.url "~" /index.html   # 对指定文件的缓存进行清理

测试:当首次访问的时候,内容从后端服务器中提取,返回信息MISS from westos
cache
,当再次访问相同的内容的时候,代理服务器上已经缓存内容,直接返回数据,返回信息HIT from westos cache

先对varnish服务器的缓存进行清理:

[root@toto1 ~]# varnishadm ban req.url "~" /

[root@toto1 ~]#

使用客户主机进行测试缓存命中情况:

[root@toto3 ~]# curl -I 172.25.47.110
HTTP/1.1 200 OK
Date: Mon, 17 Jun 2019 11:57:18 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Mon, 17 Jun 2019 11:38:06 GMT
ETag: "b-58b836e07c588"
Content-Length: 11
Content-Type: text/html; charset=UTF-8
X-Varnish: 2
Age: 0
Via: 1.1 varnish-v4
X-Cache: MISS from westos cache   # 第一次访问的时候不存在缓存内容,数据由后端服务器获取
Connection: keep-alive

[root@toto3 ~]# curl -I 172.25.47.110
HTTP/1.1 200 OK
Date: Mon, 17 Jun 2019 11:57:18 GMT
Server: Apache/2.4.6 (Red Hat Enterprise Linux)
Last-Modified: Mon, 17 Jun 2019 11:38:06 GMT
ETag: "b-58b836e07c588"
Content-Length: 11
Content-Type: text/html; charset=UTF-8
X-Varnish: 5 3
Age: 4
Via: 1.1 varnish-v4
X-Cache: HIT from westos cache  # 再次访问的时候已经有了缓存数据,命中缓存。
Connection: keep-alive

三、 定义不同域名站点的后端服务器

在使用不同的域名访问同一台代理服务器的时候,可以进行设置,将请求由发送到不同的后端服务器。

需要在代理服务器的varnish配置文件中设置多个后端服务器,并在vcl_recv 子程序中设置对不同的域名请求发送到不同的后端服务器。

vim /etc/varnish/default.vcl  # 编辑配置文件
backend web1 {
    .host = "172.25.47.120";
    .port = "80";    # 定义第一个都端服务器
}
backend web2 {
    .host = "172.25.47.130";
    .port = "80";    # 定义第二个后端服务器
}
sub vcl_recv {   
if (req.http.host ~"^(www.)?westos.org") {   # 如果请求的域名为www.westos.org或者 westos.org
        set req.http.host = "www.westos.org";   # 当将其赋值为 www.westos.org
        set req.backend_hint =web1;    # 让后将请求发送给为web1 后端服务器
}elsif (req.http.host~"^bbs.westos.org") {   # 如果请求域名为bbs.westos.org
        set req.backend_hint = web2;    # 就将请求发送给web2
}else {
        return (synth(405));   # 其他的域名返回一个405错误
}

测试:
在物理主机上做好域名解析:

vim /etc/hosts
172.25.47.110  westos.org www.westos.org bbs.westos.org

#通过不同的域名访问:
[root@foundation47 ~]# curl www.westos.org
hello toto
[root@foundation47 ~]# curl westos.org
hello toto
[root@foundation47 ~]# curl bbs.westos.org
bbs.westos.org
[root@foundation47 ~]#

四、 轮询机制实现后端服务器负载均衡

当某台后端服务器的访问压力过大的时候,可以设置多台后端服务器,提供相同的内容服务,将客户请求分配给多台服务器,减缓一台服务器的压力。

可以把多台 backends 聚合成一个组,这些组被叫做 directors。这样可以增强性能和弹力

backend web1 {
    .host = "172.25.47.120";
    .port = "80";    # 定义第一个后端服务器
}
backend web2 {
    .host = "172.25.47.130";
    .port = "80";   # 定义第二个后端服务器
}
sub vcl_init {
        new lb = directors.round_robin();   # 新建一个组
        lb.add_backend(web1);   # 将web1 添加到这个组
        lb.add_backend(web2);   # 将web2 添加到这个组
}
sub vcl_recv {
if (req.http.host ~"^(www.)?westos.org") {
        set req.http.host = "www.westos.org";
        set req.backend_hint = lb.backend();   # 发送请求循环组,让组中的后端服务器轮流处理请求
        return(pass);  # 设置直接将请求发送到后端服务器,并且不缓存返回的内容,如果进行缓存,再次访问的时候就会直接从缓存中提取内容,轮询的效果就不明显
}elsif (req.http.host~"^bbs.westos.org") {
        set req.backend_hint = web2;
}else {
        return (synth(405));
}

round_robin()这个 director 是一个循环的 director。它的含义就是 director 使用循环的方式把backends 分给请求。

测试:
为了效果明显,在web1和web2中设置的内容不一致,实际应用中,这两台服务器中提供的内容服务应该一致。

[root@foundation47 ~]# curl www.westos.org
hello toto
[root@foundation47 ~]# curl www.westos.org
www.westos.org
[root@foundation47 ~]# curl www.westos.org
hello toto
[root@foundation47 ~]# curl www.westos.org
www.westos.org

五 可以在后端服务上设置虚拟主机,当不同的域名被发送到同一个后端服务器,可以让其访问不同的内容。

后端服务器设置:

vim /etc/httpd/conf.d/vhost.conf  # 设置虚拟主机

<VirtualHost *:80>
        DocumentRoot /www
        ServerName www.westos.org
</VirtualHost>
<Directory "/www">
        Require all granted
</Directory>

<VirtualHost *:80>
        DocumentRoot /bbs
        ServerName bbs.westos.org
</VirtualHost>
<Directory "/bbs">
        Require all granted
</Directory>

#不同的虚拟主机设置不同的访问内容:
[root@toto3 ~]# cat /www/index.html 
www.westos.org
[root@toto3 ~]# cat /bbs/index.html 
bbs.westos.org
[root@toto3 ~]# 

测试:需要提前在物理主机中做好本地域名解析
目前:www.westos.org 域名会轮流在web1 和web2 之间进行轮换,bbs.westos.org 一直被发送给为web2

[root@foundation47 ~]# curl www.westos.org
hello toto
[root@foundation47 ~]# curl www.westos.org
www.westos.org
[root@foundation47 ~]# curl bbs.westos.org
bbs.westos.org
[root@foundation47 ~]

六 、配置推送平台

为了更加快捷方便及时对代理服务器中缓存内容进行清理更新。可以在代理服务器上设置网络推送页面,直接在网页上推送平台对代理服务器缓存进行修改。

1 代理服务器上安装php 以及http
由于推送平台使用的是php进行编写,需要安装php插件识别php脚本内容。

yum install php httpd  -y

更改http端口为8080,80默认端口已经被varnish占用,当以相同断空进行访问时会因为端口冲突而失败。修改完成后启动httpd服务。

2 解压平台安装包到httpd公共目录里

[root@server1 varnish]# unzip bansys.zip -d /var/www/html   # 将安装包解压到公共目录
[root@server1 varnish]# cd /var/www/html
[root@server1 html]# mv bansys/* /var/www/html  # 将解压出目录中的文件全部放到公共目录中
[root@server1 html]# ls
bansys  class_socket.php  config.php  index.php  purge_action.php  static

3 修改推送平台配置文件:

[root@server1 html]# vim config.php

在这里插入图片描述
4 修改varnish配置文件:

vim /etc/varnish/default.vcl   # 编辑配置文件

acl westos {
        "172.25.47.0"/24;   # 定义一个域,指定需要更新的网段
}

sub vcl_recv {
        if (req.method == "BAN") {
                if (!client.ip ~ westos) {   # 如果客户请求ip不是指定的网段
                return(synth(405,"Purging not allowed for " + client.ip));  # 发送一个405错误
                }
        ban("req.url ~ " + req.url);   # 客户请求的ip是指定网段,对缓存内容进行更新
                return(purge);
        }
}

systemctl restart varnish   # 重启服务

5 客户端进行测试:http://172.25.47.110:8080/

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值