HA Cluster和keepalived主从,主主高可用设置以

2019-01-23  本文已影响0人  家有猪宝_

四、简述http协议缓存原理及常用首部讲解

示例:
Expires:Thu, 13 Aug 2026 02:05:12 GMT
Cache-Control:max-age=315360000
ETag:"1ec5-502264e2ae4c0"
Last-Modified:Wed, 03 Sep 2014 10:00:27 GMT

五、简述回源原理和CDN常见多级缓存

  1. CDN:缓存网络,Content Delivery Network,即内容分发网络;加速器,向代理缓存。
  2. 基本思路:尽可能避开互联风上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础上的一层只能虚拟网络,CDN系统能够实现实时的根据网络流量和各个节点的连接、负载状况以及到永固的距离和相应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用可就近取得所需内容,解决互联网拥挤状况,提高用户访问网站的响应速度。
  3. 基本原理:广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。
  4. 服务模式:内容分发网络(CDN)是一种新型网络构建方式,它是为能在传统的IP网发布宽带丰富媒体而特别优化的网络覆盖层;而从广义的角度,CDN代表了一种基于质量与秩序的网络服务模式。
    简单地说,内容分发网络(CDN)是一个经策略性部署的整体系统,包括分布式存储、负载均衡、网络请求的重定向和内容管理4个要件,而内容管理和全局的网络流量管理(Traffic Management)是CDN的核心所在。通过用户就近性和服务器负载的判断,CDN确保内容以一种极为高效的方式为用户的请求提供服务。
    总的来说,内容服务基于缓存服务器,也称作代理缓存(Surrogate),它位于网络的边缘,距用户仅有“一跳”(Single Hop)之遥。同时,代理缓存是内容提供商源服务器(通常位于CDN服务提供商的数据中心)的一个透明镜像。这样的架构使得CDN服务提供商能够代表他们客户,即内容供应商,向最终用户提供尽可能好的体验,而这些用户是不能容忍请求响应时间有任何延迟的。
  5. GSLB:全局服务负载均衡器;调度客户请求到不同的缓存服务器上;
  6. SLB:局部负载均衡器;

六、varnish实现缓存对象及反代后端主机

官方站点:http://www.varnish-cache.org
1. varnish架构:

varnish.png

...

2. varnish的程序环境

程序选项:/etc/varnish/varnish.params文件
    -a address[:port][,address[:port][...],默认为6081端口; 
    -T address[:port],默认为6082端口;
    -s [name=]Typespe[,options],定义缓存存储机制;
    -u user
    -g group
    -f config:VCL配置文件;
    -F:运行于前台;
运行时参数:/etc/varnish/varnish.params文件, DEAMON_OPTS
    DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"

    thread_pool_min=5:最小线程数
    thread_pool_max=500:最小线程数
    thread_pool_timeout=300:线程时长
    -p param=value:设定运行参数及其值; 可重复使用多次;
    -r param[,param...]: 设定指定的参数为只读状态;
                ...

重载vcl配置文件:
    varnish_reload_vcl

命令行工具:varnishadm
    varnishadm -S /etc/varnish/secret -T [ADDRESS:]PORT

配置文件相关:
    vcl.list 
    vcl.load:装载,加载并编译;
    vcl.use:激活;
    vcl.discard:删除;
    vcl.show [-v] <configname>:查看指定的配置文件的详细信息;

运行时参数:
    param.show -l:显示列表;
    param.show <PARAM>
    param.set <PARAM> <VALUE>

缓存存储:
    storage.list
                
后端服务器:
    backend.list 

示例

[root@node2 ~]# cat /usr/lib/systemd/system/varnish.service 
[Unit]
Description=Varnish Cache, a high-performance HTTP accelerator
After=network.target

[Service]
# If you want to make changes to this file, please copy it to
# /etc/systemd/system/varnish.service and make your changes there.
# This will override the file kept at /lib/systemd/system/varnish.service
#
# Enviroment variables may be found in /etc/varnish/varnish.params
#

# Maximum number of open files (for ulimit -n)
LimitNOFILE=131072

# Locked shared memory (for ulimit -l)
# Default log size is 82MB + header
LimitMEMLOCK=82000

# On systemd >= 228 enable this to avoid "fork failed" on reload.
#TasksMax=infinity

# Maximum size of the corefile.
LimitCORE=infinity

EnvironmentFile=/etc/varnish/varnish.params    #先加载环境文件;加载后里面的变量名就可直接调用了;

Type=forking
PIDFile=/var/run/varnish.pid
PrivateTmp=true
ExecStart=/usr/sbin/varnishd \    #启动varnish
    -P /var/run/varnish.pid \    #指明pid文件
    -f $VARNISH_VCL_CONF \    #指明vcl配置文件,此处的变量就是在环境文件中定义的变量;
    -a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
    -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
    -S $VARNISH_SECRET_FILE \
    -u $VARNISH_USER -g $VARNISH_GROUP \
    -s $VARNISH_STORAGE \
    $DAEMON_OPTS    #表示为除以上常见选项外的常量;

ExecReload=/usr/sbin/varnish_reload_vcl

[Install]
WantedBy=multi-user.target

...

[root@node2 ~]# cat /etc/varnish/varnish.params    #这里定义的其实就是命令行选项:可查看unit file文件就可明白 /usr/lib/systemd/system/varnish.service
# Varnish environment configuration description. This was derived from
# the old style sysconfig/defaults settings

# Set this to 1 to make systemd reload try to switch VCL without restart.
RELOAD_VCL=1    #表示systemctl使用reload而不是restart命令时,会自动重新装载vcl配置文件,就是使vcl新配置文件生效; 

# Main configuration file. You probably want to change it.
VARNISH_VCL_CONF=/etc/varnish/default.vcl

# Default address and port to bind to. Blank address means all IPv4
# and IPv6 interfaces, otherwise specify a host name, an IPv4 dotted
# quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=192.168.1.5    #监听的地址;默认监听所有ipv4和v6地址;如果只期望监听在一个地址上时看,可启用;
VARNISH_LISTEN_PORT=6081    #用来提供服务的监听端口,varnish常作为web服务的反代,所以要改为80;但实际varnish不会真正面向客户端,而面向的是代理服务器有可能是lvs或nginx,一般是nginx或ha proxy居多,nginx和ha proxy是可以直接支持端口映射的,类似于nat机制;所以,使用6081也没什么问题;

# Admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1    #为varnish的管理接口地址;
VARNISH_ADMIN_LISTEN_PORT=6082    #为varnish管理监听的端口;

# Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret    #为varnish连接时要求认证,是预共享密钥文件,是由varnish自己生成的密钥;  

# Backend storage specification, see Storage Types in the varnishd(5)
# man page for details.
VARNISH_STORAGE="malloc,256M"    #为varnish缓存的存储格式为file方式存储,为二进制格式文件,256M是大小;VARNISH_STORAGE只是一个被unit file文件调用的变量名而已,跟varnish没有关系;

VARNISH_TTL=120    #如果后端服务器没指明生存时长,就为此处的默认值;

# User and group for the varnishd worker processes
VARNISH_USER=varnish    #运行varnish进程的用户名、组名;
VARNISH_GROUP=varnish

# Other options, see the man page varnishd(1)
#DAEMON_OPTS="-p thread_pool_min=5 -p thread_pool_max=500 -p thread_pool_timeout=300"
    其中:Run-Time Parameters运行时参数包括很多:
    thread_pools 线程池个数,需要定义;
        Default: 2 默认为2个;
        Minimum: 1 最少为1个;
    thread_pool_min 定义每个线程池中的最少个数;
        Default: 100 默认为100个;
        Maximum: 5000 最多为5000个;
    thread_pool_max 定义每个线程池中的最多个数;
        Default: 5000 默认为5000个;
        Minimum: 100 最少为100个;
    这些运行时参数,都可以使用-p param=value指定;

3. VCL:varnish configuration language

Varnish Finite State Machine

  1. 其中一种响应方式有可能是不运行客户端访问,直接拒绝;
  2. 还有可能的第二种方式,请求进来时分析发现,是正常请求,于是判断资源类型的是否是可缓存的,如果是可缓存的,例如用户请求的get方法,因为get方法是可以查缓存的,就开始查找缓存,如果缓存命中了直接返回给客户端;
  3. 如果发现请求的资源类型缓存未命中,则varnish要到后端服务器读取,取回来之后在响应给客户端;
  4. 如果发现请求的资源类型是不可缓存的,因为用post或put方法就不可缓存,于是直接到后端服务器读取;例如上传一个文件或提交一个表单;后端服务器响应给varnish后,再响应给客户端;
            vcl_recv的默认配置:
            
                sub vcl_recv {
                    if (req.method == "PRI") {
                        /* We do not support SPDY or HTTP/2.0 */
                        return (synth(405));
                    }
                    if (req.method != "GET" &&
                    req.method != "HEAD" &&
                    req.method != "PUT" &&
                    req.method != "POST" &&
                    req.method != "TRACE" &&
                    req.method != "OPTIONS" &&
                    req.method != "DELETE") {
                        /* Non-RFC2616 or CONNECT which is weird. */
                        return (pipe);
                    }

                    if (req.method != "GET" && req.method != "HEAD") {
                        /* We only deal with GET and HEAD by default */
                        return (pass);
                    }
                    if (req.http.Authorization || req.http.Cookie) {
                        /* Not cacheable by default */
                        return (pass);
                    }
                        return (hash);
                    }
                }
sub subroutine {
          ...
      }
      
      if CONDITION {
          ...
      } else {    
          ...
      }
      
      return(), hash_data()

示例:obj.hits是内建变量,用于保存某缓存项的从缓存中命中的次数;
        [root@node2 ~]# vim /etc/varnish/default.vcl 
            #在其中sub vcl_deliver {...}段中添加如下内容
            if (obj.hits>0) {
                    set resp.http.X-Cache = "HIT via " + server.ip;
                } else {
                    set resp.http.X-Cache = "MISS via " + server.ip;
                }      
        
        [root@node2 ~]# varnishadm
        vcl.load test2 default.vcl
        200        
        VCL compiled.
        vcl.list
        200
        active          0 test1
        available       0 test2
        vcl.use test2
        vcl.use test2
        200        
        VCL 'test2' now active

vcl变量可用范围.png

@R/W:能读能修改;R:只读;

示例:强制对某资源的请求不检查缓存
  # 在BE主机上添加2个路径和index.html资源
[root@server2 ~]# mkdir /var/www/html/{admin,login}
[root@server2 ~]# ls /var/www/html/
admin  index.html  login
[root@server2 ~]# vim /var/www/html/admin/index.html
<h1>Admin App</h1>
[root@server2 ~]# vim /var/www/html/login/index.html
<h1>Login App</h1>

# 在varnish主机上修改配置文件
[root@node2 varnish]# vim default.vcl
# 在 sub vcl_recv 中添加如下内容
 if (req.url ~ "(?i)^/(login|admin)") {
        return(pass);
    }
# 回到varnish命令行:使vcl配置生效

[root@node2 varnish]# varnishadm
vcl.load test3 default.vcl
200        
VCL compiled.
vcl.list
200        
active          0 boot
available       0 test3

vcl.use test3
200        
VCL 'test3' now active

访问测试


admin-x-cache.png
示例:不能使用curl访问
  #在varnish主机上修改配置文件
  [root@server1 varnish]# vim default.vcl
  #在 sub vcl_recv {...}中添加如下内容
   if (req.http.User-Agent ~ "(?i)curl") {
        return(synth(406));
    }  

  # 回到varnish命令行:使vcl配置生效
  vcl.load test6 default.vcl
  200        
  VCL compiled.
  vcl.use test6
  200        
  VCL 'test6' now active

  # client使用curl访问测试
[root@rs2 ~]# curl http://192.168.1.10
<!DOCTYPE html>
<html>
  <head>
    <title>406 Not Acceptable</title>
  </head>
  <body>
    <h1>Error 406 Not Acceptable</h1>
    <p>Not Acceptable</p>
    <h3>Guru Meditation:</h3>
    <p>XID: 20</p>
    <hr>
    <p>Varnish cache server</p>
  </body>
</html>

...

示例:对于特定的资源,例如公开的图片等取消其私有标识,并强行设定其可以由varnish缓存时间长
    # 在BE主机上准备图片

    [root@rs1 ~]# find /usr/share -iname "*.jpg" -exec cp {} /tmp/image/ \; 
    # 修改varnish的vcl配置,在default.vcl中的sub vcl_backend_response {...}中添加如下内容
    if (beresp.http.cache-control !~ "(?i)s-maxage") {
        if (bereq.url ~ "(?i)\.(jpg|jpeg|png|gif|css|js)") {
            unset beresp.http.Set-Cookie;
            set beresp.ttl=3600s;
        }   
    }
# 回到varnish命令行:使vcl配置生效
vcl.load test7 default.vcl
200        
VCL compiled.
vcl.use test7
200        
VCL 'test7' now active

使用client访问测试:


vcl-7.png
示例:使BE主机访问日志里记录client的真实ip地址
    # 在sub vcl_recv {...}中添加如下内容
    if (req.restarts == 0) {
        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;
        }
    }

# 回到varnish命令行:使vcl配置生效
vcl.load test8 default.vcl
200        
VCL compiled.
vcl.use test8
200        
VCL 'test8' now active

# 修改BE主机的访问日志格式
[root@rs1 ~]# cd /etc/httpd/conf/
[root@rs1 conf]# vim httpd.conf
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

# 使用client访问后查看access_log
[root@rs1 conf]# tail -2 /var/log/httpd/access_log
192.168.1.1 - - [21/Jan/2019:10:02:24 +0800] "GET /fish.jpg HTTP/1.1" 200 3225 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
192.168.1.1 - - [21/Jan/2019:10:11:05 +0800] "GET /admin/ HTTP/1.1" 304 - "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"

示例:

sub vcl_recv {...}中定义执行purge操作

   if (req.method == "PURGE") {
        return(purge);
    }

定义purge的操作方式

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

回到varnish命令行:使vcl配置生效

vcl.load test9 default.vcl
200        
VCL compiled.
vcl.use test9
200        
VCL 'test9' now active

使用client访问测试:

[root@rs2 ~]# curl -I http://192.168.1.10
  HTTP/1.1 200 OK
  Date: Mon, 21 Jan 2019 10:23:40 GMT
  Server: Apache/2.4.6 (CentOS) PHP/5.4.16
  Last-Modified: Mon, 21 Jan 2019 10:23:40 GMT
  ETag: "1a-574cf13c0f7fa"
  Content-Length: 26
  Content-Type: text/html; charset=UTF-8
  X-Varnish: 32825 54
  Age: 29
  Via: 1.1 varnish-v4
  X-Cache: HIT via192.168.1.10
  [root@node2 ~]# curl -X PURGE http://192.168.1.10
  <!DOCTYPE html>
  <html>
    <head>
      <title>200 Purged</title>
    </head>
    <body>
      <h1>Error 200 Purged</h1>
      <p>Purged</p>
      <h3>Guru Meditation:</h3>
      <p>XID: 58</p>
      <hr>
      <p>Varnish cache server</p>
    </body>
  </html>

示例
#在default.vcl配置文件中定义访问控制,位置放在vcl 4.0之下即可
      acl purge {
          "127.0.0.1";
          "192.168.0.0/24";
          }
  #在sub vcl_recv{...}中添加访问控制内容
      if (req.method == "PURGE") {
              if (!client.ip ~ purgers ) {
                      return(synth(405,"Purging not allowed for"+ client.ip));
                      }
              return(purge);
              }
  #回到varnish命令行:使vcl配置生效
  vcl.load test10 default.vcl
  200        
  VCL compiled.
  vcl.use test10
  200        
  VCL 'test4' now active

#使用client访问测试
  [root@rs2 ~]# curl -X PURGE http://192.168.1.10
  <!DOCTYPE html>
  <html>
    <head>
      <title>405 Purging not allowed for192.168.1.20</title>
    </head>
    <body>
      <h1>Error 405 Purging not allowed for192.168.1.20</h1>
      <p>Purging not allowed for192.168.1.20</p>
      <h3>Guru Meditation:</h3>
      <p>XID: 32834</p>
      <hr>
      <p>Varnish cache server</p>
    </body>
  </html>


示例:
          (1) #在BE主机上准备访问环境
          [root@rs1 conf]# mkdir /var/www/html/javascripts
          [root@rs1 conf]# vim /var/www/html/javascripts/test1.js
          #使用client多访问几次有缓存后
          [root@rs2 ~]# curl -I http://192.168.1.10/javascripts/test1.js
          HTTP/1.1 200 OK
          Date: Mon, 21 Jan 2019 11:23:40 GMT
          Server: Apache/2.4.6 (CentOS) PHP/5.4.16
          Last-Modified: Mon, 21 Jan 2019 11:23:40 GMT
          ETag: "6-574e4abccb0ee"
          Content-Length: 6
          Content-Type: application/javascript
          X-Varnish: 75 32846
          Age: 30
          Via: 1.1 varnish-v4
          X-Cache: HIT via192.168.1.10
          Connection: keep-alive
          #到varnish命令行模式,手动清理
          ban req.url ~ ^/javascripts
          200 
          #再次使用client访问测试
          [root@rs2 ~]# curl -I http://192.168.1.10/javascripts/test1.js
          ...
          X-Cache: Miss via192.168.1.10
          ...
          (2) 在配置文件中定义,使用ban()函数;
          #在 sub vcl_recv {...}中定义如下内容
          if (req.method == "BAN") {
              ban("req.http.host == " + req.http.host + " && req.url == " + req.url);
              # Throw a synthetic page so the request won't go to the backend.
              return(synth(200, "Ban added"));
          }               
          #回到varnish命令行,使配置文件生效
          vcl.load test11 default.vcl
          200        
          VCL compiled.
          vcl.use test11
          200        
          VCL 'test11' now active


提供php动态资源测试页:
      ]# vim /var/www/html/index.php
      <?php
      phpinfo();
      ?>
      #后端静态主机为默认主机default
  
      #在vcl添加多台后端主机:
      ]# vim /etc/varnish/default.vcl
      添加:
      backend appsrv {
          .host = "192.168.1.21";
          .port = "80";
      }
      
      sub vcl_recv {
          if (req.url ~ "(?i)\.php$") {
              set req.backend_hint = appsrv;
          } else {
              set req.backend_hint = default;
          }
      
      vcl.load test12 default.vcl
      200        
      VCL compiled.
      vcl.use test12
      200        
      VCL 'test6' now active

client使用浏览器访问测试:


vcl12-php.png vcl12-html.png
示例2:
    import directors;    # load the directors

            backend server1 {
                .host = "192.168.1.20";
                .port = "80";
            }
            backend server2 {
                .host = "192.168.1.21";
                .port = "80";
            }

            sub vcl_init {
                new servers = directors.round_robin();
                servers.add_backend(server1);
                servers.add_backend(server2);
            }

            sub vcl_recv {
                # send all traffic to the bar director:
                set req.backend_hint = servers.backend();
            }
            vcl.load test13 default.vcl
            200        
            VCL compiled.
            vcl.use test13
            200        
            VCL 'test9' now active

示例:
          sub vcl_init {
              new h = directors.hash();
              h.add_backend(one, 1);   // backend 'one' with weight '1'
              h.add_backend(two, 1);   // backend 'two' with weight '1'
          }

          sub vcl_recv {
              // pick a backend based on the cookie header of the client
              set req.backend_hint = h.backend(req.http.cookie);
          }


示例:
      probe check {
          .url = "/.healthcheck.html";
          .window = 5;
          .threshold = 4;
          .interval = 2s;
          .timeout = 1s;
      }

      backend default {
          .host = "10.1.0.68";
          .port = "80";
          .probe = check;
      }

      backend appsrv {
          .host = "10.1.0.69";
          .port = "80";
          .probe = check;
      }

backend BE_NAME {
          ...
          .connect_timeout = 0.5s;
          .first_byte_timeout = 20s;
          .between_bytes_timeout = 5s;
          .max_connections = 50;
      }

上一篇 下一篇

猜你喜欢

热点阅读