CDN

CDN(content delivery network):内容分发网络,可以解决不同地域的用户访问同一网站出现的网络延迟的问题,解决方案就是在距离最近的地方部署服务节点,该节点从源站缓存数据,这种方式既可以缓解源站的压力,提高源站的安全性,加快用户的访问速度,可用性高

CDN分类:

  • 静态页面:HTML、CSS、JS、image、video
  • 流媒体:
  • 大文件:

推送类型

  • 源站主动推送数据到缓存节点:所有用户访问时都有加速效果
  • 缓存节点拉取源站数据:第一个用户访问时没有加速效果

HTML

html:超文本标记语言

http:超文本传输协议,端口号80,用来传输例如html这样的超文本文件。遵循C/S架构,实现浏览器与web服务之间的通信,无状态协议

状态报文

请求报文:客户端发送

  • 请求行 URL:统一资源定位符 协议  域名/主机名/IP  端口  资源的路径 http://www.shuaiguoer.com/varnish/test.html 请求方法: GET:下载服务端指定的资源 POST:将指定的文件上传到服务端指定的位置,如果服务端已经存在要上传的同名文件,则不进行上传 PUT:将指定的文件上传到服务端指定的位置 ,如果服务端已经存在要上传的同名文件,则覆盖 DELETE:删除指定的服务端的文件 HEAD:只获取响应报文的起始行和响应头部的信息 OPTIONS:询问服务端支持的请求方法 HTTP协议版本:HTTP/0.9--->HTTP1.0--->HTTP1.1--->HTTP2.0 1991--HTTP/0.9 GET URL 1996--HTTP/1.0 不支持虚拟主机 不支持长连接 1997--HTTP/1.1 2014--HTTP/2.0
  • 请求头部 Acceppt:记录客户端能够解析的页面类型。Accept:text/html、text/xml、text/css、image/jpeg、image/png、video/mp3、video/mp4、application/javascript Accept-Encoding:记录客户端支持的编码类型。Accept-Encoding:gzip、deflate Connections:记录客户端与服务端之间的连接方式 。Connections:closed        keep-alived Authorization:记录客户端的身份验证信息 Host:记录客户端访问的服务端的域名/主机名/    Host:www.shuaiguoer.com X-Forward-For:记录请求报文经过的客户端与代理服务器的IP地址。X-Forward-For:client_ip,proxy1_ip,proxy2_ip User-Agent:记录着浏览器版本,使用的内核等信息
  • <空行>
  • 请求主体

响应报文:服务端发送

  • 起始行 状态码: 100:表示服务端已经成功接收请求,但是还未响应 200:表示服务端已经成功接收请求,并且已经成功做出响应 201:表示服务端已经成功接收请求,并且已经成功做出响应,并且对服务端的资源做出来改变 301:永久重定向 302:临时重定向 403:对要访问的资源没有权限 404:找不到客户端要访问的资源 405:对访问的站点没有权限 500:未知因素导致服务不可用 503:服务当前处于超载状态,暂时不能接受客户端的请求 状态信息: 对状态码的一个描述 200         OK 404         NOT  FOUND 405         NOT  ALLOWED HTTP协议版本:要求与客户端的HTTP协议版本一致
  • 响应头部 Cache-Control:记录代理服务器和客户端是否允许缓存响应报文,以及缓存的时间。Cache-Control:public, maxage-100000 Content-Type:记录服务端响应的数据的页面类型 Content-Length:记录响应报文的长度,单位为字节 Contention:记录服务端与客户端之间的连接类型 Date:记录响应报文从服务端发出的时间 Server:记录web服务信息及web服务版本号
  • <空行>
  • 响应主体

一个能够记录超文本数据的语言          HTML

一个能够传输超文本文件的协议          HTTP

一个能够表示超文本文件的客户端      浏览器

一个能够提供超文本文件的服务端      web服务器:nginx、apache、...

连接方式

  • 长连接
  • 短连接
  • 流水线连接

VCL语法

Vcl 4.0;
#运算符:
=:赋值运算符
==:比较运算符,是否相等
!=:是否不等于
!:非
~:匹配正则表达式
!~:不匹配
&&:与  and
|| :或  or
数据类型:
字符串:“asdbjnsvja”+“sduahbjsndvjnl”
整数:123456789
有效时间:s,m,h,d,w,y,

条件表达式

if (条件){
条件成立要执行的代码块
}
else {
条件不成立要执行的代码块
}
if (条件1){
条件1成立要执行的代码块
}
elseif (条件2) {
条件不成立时判断条件2
条件2成立要执行的代码块
}
......
else{
所有条件都不成立时要执行的代码块
}

指定要代理的后端服务节点

backend alias{
        .hist=”ip/domain_name/hostname”;
        .port=”端口”;
        .connect_timeout=30s; #反向代理与服务节点的连接超时时间
        .max_connections=200; #服务节点同一时间的最大连接量
        .probe=”alias”
}

健康检查模块

probe alias{
        .url=”/”; 要检查的服务端的url
        .timeout=3s; 代理与服务端的连接超时时间
        .interval=2s; 每隔2s对服务节点做一次健康检查
        .window=5; 每次健康检查代理服务端发送5个窗口
        .threshold=3; 代理收到最少三个窗口响应就认为服务端可用
}

负载调度模块

import directors: #导入负载调度模块
sub vcl_init{
        new back=directors.roundrobin(); #轮询
        new back=directors.fallback(); #按顺序找到第一台可用的服务节点并将请求交给该节点
        new back=directors.hash(); #哈希
        new back=directors.random(); #随机
        back.add_backend(web1); #将调度算法用到节点
        back.add_backend(web2); 
}
#访问控制列表
acl alias{
“ip”;
“hostname”;
“domain_name”;
}

变量

设置变量

set

取消变量

unset

预设变量

req:客户端给varnish发送请求使用的变量

  •     req-method:客户端请求报文中使用的请求方法
  •     req-url:客户端请求报文中的URL
  •     req-http:客户端请求报文中的请求头部
  •     req_backend_hint:当客户端的请求varnish处理不了时交给哪个服务节点处理

bereq:varnish给服务节点发送请求时使用的变量

  •     bereq.url:varnish发送给服务节点的请求报文总的URL
  •     bereq.http:varnish发送给服务节点的请求报文中的请求头部

resp:varnish响应客户端使用的变量

  •     resp.http:varnish响应客户端的响应报文使用的响应头部

beresp:服务节点响应varnish使用的变量

  •     beresp.uncacheable:服务节点响应varnish的数据是否需要varnish缓存
  •     beresp.ttl:服务节点响应varnish的数据如果要缓存的缓存时间

obj:缓存在varnish本地的数据使用的变量

  •     obj.ttl:缓存在varnish中的对象的缓存时间
  •     obj.hits:缓存在varnish中的对象的命中次数

hash_data():varnish在本地查找缓存的数据使用的变量

  •     hash_data(req.url):根据客户端请求的URL在varnish缓存中查找
  •     hash_data(req.http.host):根据客户端请求的主机名在varnish缓存中查找
  •     hash_data(server.ip):根据客户端请求的服务端的IP地址在varnish缓存中查找

状态引擎/子模块

  • vcl_recv:接收客户端的请求并处理
  • vcl_hash:在varnish缓存中查找客户端请求的数据
  • vcl_hit:命中,能够在varnish缓存中找到客户端请求的数据
  • vcl_miss:未命中,不能再varnish缓存中找到客户端请求的数据
  • vcl_pass:客户端请求的数据为动态数据时使用该模块
  • vcl_pipe:客户端的请求不正当是使用该模块
  • vcl_backend_response:将请求交给后端节点并接收后端节点返回的响应
  • vcl_deliver:varnish返回数据给客户端
  • vcl_init:初始化模块
  • vcl_purge:清除缓存

varnish的特点

  1. 将数据缓存到内存中,支持虚拟内存,I/O性能好,不支持数据的持久化,服务重启或服务器故障会丢失
  2. 对数据的缓存时间可以精确到秒
  3. 可以通过VCL来进行配置
  4. 支持多种状态引擎
  5. 支持多种管理工具

varnish的安装

安装依赖包

[root@localhost ~]# yum -y install automake autoconf libtool ncurses-devel pcre-devel pkgconfig graphviz
# 自行下载以下软件包并安装
[root@localhost ~]# rpm -ivh jemalloc-devel-5.2.0-1.1.x86_64.rpm --nodeps
[root@localhost ~]# rpm -ivh libedit-3.0-12.20121213cvs.el7.x86_64.rpm --nodeps
[root@localhost ~]# rpm -ivh libedit-devel-3.0-12.20121213cvs.el7.x86_64.rpm --nodeps
[root@localhost ~]# rpm -ivh python-docutils-0.11-0.3.20130715svn7687.el7.noar.rpm --nodeps
[root@localhost ~]# rpm -ivh python-Sphinx-1.6.5-3.10.1.noarch.rpm --nodeps

编译安装varnish

[root@localhost ~]# tar -zxvf varnish-4.1.11.tgz 
[root@localhost ~]# cd varnish-4.1.11/
[root@localhost varnish-4.1.11]# ./configure --prefix=/usr/local/varnish && make && make install

路径优化

[root@localhost ~]# ln -s /usr/local/varnish/sbin/* /usr/local/sbin/
[root@localhost ~]# ln -s /usr/local/varnish/bin/* /usr/local/bin/

编写vcl代码

[root@localhost ~]# cd /usr/local/varnish/
[root@localhost varnish]# vim default.vcl
vcl 4.0;

probe health {
        .url="/";
        .timeout=4s;
        .interval=2s;
        .window=5;
        .threshold=3;
}

backend web {
        .host="192.168.1.11";
        .port="80";
        .probe=health;
}

sub vcl_recv {
        set req.backend_hint=web;
        if (req.http.X-Forwarded-For) {
                set req.http.X-Forwarded-For = req.http.X-Forwarded-For + "," + client.ip;
        }
        else {
                set req.http.X-Forwarded-For = client.ip;
        }
        if (req.method != "GET" && req.method != "PUT" && req.method != "POST" && req.method != "HEAD" && req.method != "DELETE" && req.method != "OPTIONS") {
                return (pipe);
        }
        if (req.url ~ "\.php$") {
                return (pass);
        }
        if (req.url ~ "\.(html|htm|xml|css|jpg|png|mp3|mp4|tar|gz|zip)$") {
                return (hash);
        }
}

sub vcl_pipe {
        return (pipe);
}

sub vcl_pass {
        return (fetch);
                set req.http.X-Forwarded-For = client.ip;
        }
        if (req.method != "GET" && req.method != "PUT" && req.method != "POST" && req.method != "HEAD" && req.method != "DELETE" && req.method != "OPTIONS") {
                return (pipe);
        }
        if (req.url ~ "\.php$") {
                return (pass);
        }
        if (req.url ~ "\.(html|htm|xml|css|jpg|png|mp3|mp4|tar|gz|zip)$") {
                return (hash);
        }
}

sub vcl_pipe {
        return (pipe);
}

sub vcl_pass {
        return (fetch);
}

sub vcl_hash {
        hash_data(req.url);
        if (req.http.host) {
                hash_data(req.http.host);
        }
        else {
                hash_data(server.ip);
        }
}

sub vcl_hit {
        return (deliver);
}

sub vcl_miss {
        return (fetch);
}

sub vcl_backend_response {
        if (bereq.url ~ "\.php$") {
                set beresp.uncacheable = true;
                return (deliver);
        }
        if (bereq.url ~ "\.html$") {
                set beresp.ttl = 10s;
                return (deliver);
        }
}

sub vcl_deliver {
        if (obj.hits > 0) {
                set resp.http.X-Cache = "Hitttttttttt";
        }
        else {
                set resp.http.X-Cache = "Misssssssssss";
        }
}

检查语法

[root@localhost varnish]# varnishd -C -f default.vcl

PURGE

Varnish启动项

  • -a : 指定varnish启动时监听的IP与端口
  • -f : 启动时指定varnish要加载的配置文件
  • -P : 指定varnish的进程文件存放位置及命名
  • -n : 指定varnish的工作目录
  • -S : 登录到平台使用的秘钥文件
  • -T : 登录到管理平台使用的IP与端口
  • -s : 指定varnish缓存文件存放路径及命名
  • -p : 指定varnish运行时要加载到参数
  • Thread_pools:varnish启动时加载几个线程池
  • Thread_pool_min:每个线程池中最少开启几个空线程
  • Thread_pool_max:每个线程池最多开启几个空闲线程
  • Thread_pool_timeou:当规定的时间内没有新的请求时,会对线程池中的线程进行释放,直到线程的数量最小或者等于最少空闲线程数规定规定值
  • Lru_interval:设置lru时间,也就是如果varnish缓存的数据没有设置缓存时间,也就是如果varnish缓存的数据没有设置时间,并且数据很久没有被访问,那么在该时间的范围内没有被访问的数据将会从内存中释放

varnish管理工具

  • Varnishadm:varnish命令行管理工具
  • Varnishlog:varnish日志工具
  • Varnishncsa:varnish日志工具,以http日志格式显示
  • Varnishstat:varnish状态监控工具

配置

vcl 4.0;

probe health {
        .url="/";
        .timeout=3s;
        .interval=2s;
        .window=5;
        .threshold=3;
}

backend webA {
        .host="192.168.10.4";
        .port="80";
        .probe=health;
}

backend webB {
        .host="192.168.10.5";
        .port="80";
        .probe=health;
}

import directors;
sub vcl_init {
        new back=directors.round_robin();
        back.add_backend(webA);
        back.add_backend(webB);
}

acl allow {
        "localhost";
        "127.0.0.1";
        "192.168.10.1";
}

sub vcl_recv {
        set req.backend_hint = back.backend();
        if (req.method == "PURGE"){
                if(client.ip ~ allow){
                        return (purge);
                }
                else{
                        return (synth(405,"NOT ALLOWED"));
                }
        }
        if (req.method !="GET" && req.method !="PUT" && req.method !="POST" && req.method !="DELETE" && req.method != "HEAD" && req.method !="OPTIONS") {
                return (pipe);
        }
        if (req.url ~ "\.(php|jsp|do)$") {
                return (pass);
        }
        if (req.method !="GET" && req.method !="MEAD") {
                return (pass);
        }
        if (req.http.Authorizetion) {
                return (pass);
        }
        if (req.url ~ "\.(html|htm|css|xml|jpg|jpeg|gif|tar|gz|zip|bzip2|mp3|mp4|)$"){
                return(hash);
        }
        if (req.http.Accept-Encoding) {
                if (req.url ~ "\.(tar|gz|zip|bzip2|rar|jpeg|mp3|mp4)$"){
                        unset req.http.Accept-Encoding;
                }
                elseif (req.http.Accept-Encoding ~ "gzip") {
                        set req.http.Accept-Encoding = "gzip";
                }
                elseif (req.http.Accep-Encoding ~ "deflate"){
                        set req.http.Accept-Encoding= "deflate";
                }
                else {
                        unset req.http.Accept-Encoding;
                }
        }
}

sub vcl_pipe{
        return (pipe);
}

sub vcl_pass{
        return (fetch);
}

sub vcl_hash{
        hash_data(req.url);
        if(req.http.host){
                hash_data(req.http.host);
        }
        else{
                hash_data(server.ip);
        }
        if (req.http.Accept-Encoding ~ "gzip"){
                hash_data("gzip");
        }
        elseif(req.http.Accept-Encoing ~ "deflate"){
                hash_data("deflata");
        }
}

sub vcl_hit {
        return (deliver);
}

sub vcl_miss {
        return (fetch);
}

sub vcl_backend_response {
        if (bereq.url ~ "\.(php|jsp|do)$"){
                set beresp.uncacheable = true;
                return (deliver);
        }
        if (bereq.url ~ "\.(htm|html|css|xml)$"){
                set beresp.ttl = 10s;
                return (deliver);
        }
        if (bereq.url ~ "\.(jpg|jpeg|png|gif)$"){
        set beresp.ttl = 7d;
        return (deliver);
        }
        if (bereq.url ~ "\.(mp3|mp4)$"){
        set beresp.ttl = 30d;
        return (deliver);
        }
}

sub vcl_purge {
        return (synth(200,"PURGED"));
}

sub vcl_deliver {
        if (obj.hits > 0) {
                set resp.http.X-Cache = "HIT";
        }
        else{
                set resp.http.X-Cache = "MISS";
        }
        return (deliver);
}
Last modification:July 23rd, 2020 at 09:40 pm
如果觉得我的文章对你有用,请随意赞赏