• Varnish 问题点 与 技术方案 Varnish 优劣分析


     
    A10 有没有能做热点统计
     
    1 Varnish 分布式 HA  (目前没有HA)
    2 Varnish 热点监控     (建议热点需要外部插件统计,API的话目前并木有发现,但是他自带一个伪热点功能)
    如果用外部插件统计热点。  热点的读写Varnish 比较有难度。 Varnish是VCL语言编写。 而配置文件使用C语言方法。
     
    Varnish的优势
     
    Varnih 的对比Squid可靠性高,Squid服务器发生故障的几率要高于Varnish,因为使用Squid要经常重启;
     
    Varnish 采用了“Visual Page Cache”技术,缓存数据内存读,squid是从硬盘读取
     
    Varnish 支持多并发连接,因为Varnish的TCP连接释放要比Squid快,因而在高并发连接情况下可以支持更多TCP连接;
     
    Varnish 可以通过管理端口,使用正则表达式批量的清除部分缓存,而Squid是做不到的;
     
    squid 属于是单进程使用单核CPU,但 Varnish 是通过 fork 形式打开多进程来做处理,所以可以合理的使用所有核来处理相应的请求;
     
    Varnish的劣势
     
    varnish进程一旦Hang、Crash或者重启,缓存数据都会从内存中完全释放,此时所有请求都会发送到后端服务器,在高并发情况下,会给后端服务器造成很大压力;
     
    在varnish使用中如果单个url的请求通过HA/F5等负载均衡,则每次请求落在不同的varnish服务器中,造成请求都会被穿透到后端;而且同样的请求在多台服务器上缓存,也会造成varnish的缓存的资源浪费,造成性能下降;
     
     
    Varnish劣势的解决方案
     
    针对劣势一:在访问量很大  
    的情况下推荐使用varnish的内存缓存方式启动,而且后面需要跟多台squid服务器。主要为了防止前面的varnish服 务、服务器被重启的情况下,大量请求穿透varnish,这样squid可以就担当第二层CACHE,而且也弥补了varnish缓存在内存中重启都会释 放的问题;
     
    针对劣势二:可以在负载均衡上做url哈希,让单个url请求固定请求到一台varnish服务器上;  
     
    可以数据存硬盘上。  热点数据车存储在 SSD 硬盘。
     
    可行性分析整理: 
       两台 Varnish 机器做HA(两台机器分别安装Varnish且不同步)(伪同步 HA 可保证) 
       缺点:将会造成冗余存储。 两台机器缓存较多为一致。 
       优点:如果出现一台机器宕机。可以避免大量请求压死后端、且伪同步可以节省部分内存空间,过滤掉量小的请求。并集才会存储在内存中。
     
     热点分析问题:
       如果要做热点分析,Varnish 内部是不支持的, 需要外部插件做。且需要C方便的哥们志愿一下写内存插入功能。
       建议:varnish 中没有热点分析。 但是有命中数统计。 可以设置超过一定命中数后 设置TTL的值。  还可以设置 varnish 缓存此图片的时间延长。
     
    Varnish 是 VCL语言编写的
    解析方式是讲配置文件方法转成 C 编译执行。
     
     
     
     
    vcl_fetch 在一个文件成功从后台获取后被调用,通常他的任务就是改变 response headers,触发 ESI 进程,在请求失败的时候轮询其他服务器。{
    actions
    主要有以下动作
    pass  \请求转发后端服务器不缓存
    lookup \当请求在 vcl_recv 中被 lookup 后,varnish 将从缓存中提取数据,如果缓存中没有数据,将被设置为 pass,不能在 vcl_fetch 中设置 lookup。
    pipe \pipe 和 pass 相似,都要访问后端服务器,不过当进入 pipe 模式后,在此连接未关闭前,后续的所有请求都发到后端服务器(这句是我自己理解后简化的,有能力的朋友可以看看官方文档,给我提修改建议) 。
    deliver \请求的目标被缓存,然后发送给客户端
    esi \ESI-process the fetched document(我理解的就是 vcl 中包换一段 html
    }
     
    Statistics (统计 varnish  相关数据)
    现在您的 varnish 已经正常运行,我们来看一下 varnish 在做什么,这里有些工具可
    以帮助您做到。
    Varnishtop
    Varnishtop工具读取共享内存的日志, 然后连续不断的显示和更新大部分普通日志。
    适当的过滤使用 –I,-i,-X 和-x 选项,它可以按照您的要求显示请求的内容,客
    户端,浏览器等其他日志里的信息。
    varnishtop -i rxurl \您可以看到客户端请求的 url 次数。
    Varnishtop -i txurl \您可以看到请求后端服务器的 url 次数。
    Varnishtop -i Rxheader –I Accept-Encoding \可以看见接收到的头信息中有有多少次
    包含 Accept-Encoding。
    Varnishstat
    Varnish 有很多计数器,我们计数丢失率,命中率,存储信息,创建线程,删除对
    象等,几乎所有的操作。Varnishstat 将存储这些数值,在优化 varnish 的时候使用这个命令。
    有一个程序可以定期轮询 varnishstat 的数据并生成好看的图表。这个项目叫做
    Munin。 Munin 可以在 http://munin-monitoring.org/找到。 在 varnish 的源码中有 munin 插件。
     
    ——————————————————————————————————————————————————————————————————————————————
     
     
                                                                                                            技术笔记
     
            varnish 有一个概念叫做“后端服务器”或者叫“原点服务器” ,一个后端服务器将提供 varnish 加速的内容。我们的第一个任务就是告诉 varnish 在哪里可以找到他要的内容。如果您是源码安装的配置文件可能在
    varnish(3.0.0)/etc/default.vcl 配置详解
    /etc/varnish/default.vcl.
    配置文件的最顶端如下:
    backend default {
      .host = "127.0.0.1";
      .port = "80";
    }
     
    现在,这块配置定义了一个 varnish 默认访问的后端服务器,当 varnish 需要从后端
    服务器获取内容的时候,它就会访问自己(127.0.0.1)的 80 端口。
    Varnish 可以定义多个后端服务器而且您可以通过定义多个后端服务器达到负载均
     
    backend server2 {
    .host = "server2.example.com";
    .probe = {
    .url = "/";
    .interval = 5s;
    .timeout = 1 s;
    .window = 5;
    .threshold = 3;
    }
    }
    这些新的就是探针,varnish 将检查通过探针检查每个后端服务器是否健康:
    url \哪个 url 需要 varnish 请求。
    Interval \检查的间隔时间
    Timeout \等待多长时间探针超时
    Window \varnish 将维持 5 个 sliding window 的结果
    Threshold  \至少有 3 次.windows 检查是成功的,就宣告 backends 健康
     
     
     
     
    的目的。
    命令 示例: 
    varnishd -f /usr/local/etc/varnish/default.vcl -s malloc,1G -T 127.0.0.1:2000 -a 0.0.0.0:8080
     
    varnishd -f /usr/local/etc/varnish/default.vcl
            指定 Varnish 使用哪个配置文件 。
    -s malloc,1G
            –s 选项用来确定 varnish 使用的存储类型和存储容量,我使用的是 malloc 类型(malloc 是一个 C 函数,用于分配内存空间)  1G 定义多少内存被 malloced,1G =1gigabyte
    -T 127.0.0.1:2000
            Varnish 有一个基于文本的管理接口,启动它的话可以在不停止 varnish 的情况下来管理 varnish。您可以指定管理软件监听哪个接口。当然您不能让全世界的人都能访问您的varnish 管理接口, 因为他们可以很轻松的通过访问 varnish 管理接口来获得您的 root 访问权限。我推荐只让它监听本机端口。如果您的系统里有您不完全信任的用户,您可以通过防火墙规则来限制他访问 varnish 的管理端口
    -a 0.0.0.0:8080
            这一句的意思是制定 varnish 监听所有 IP 发给 8080 端口的 http 请求,如果在生产环境下,您应该让 varnish 监听 80,这也是默认的。
     
     
     
    Varnish 支持将数据写硬盘上
     
     
    VCL 支持以下运算符,请阅读下面的例子:
    =  \赋值运算符
    == \对比
    ~  \匹配,在 ACL 中和正则表达式中都可以用
    ! \否定
    && \逻辑与
    ||  \逻辑或
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     Varnish配置文件详解

    既然Varnish需要在多台服务器上缓存数据,就需要Varnish映射所有的URL到一台单独的主机。

    
    
    1. backend webserver {  
    2. .host = "127.0.0.1";  
    3. .port = "80";  
    4. .connect_timeout = 4s;  
    5. .first_byte_timeout = 5s;  
    6. .between_bytes_timeout = 20s;  
    7. }  

    该块配置用于定义一台Varnish默认访问的后端服务器,当Varnish需要从后端服务器获取数据时,就会访问自己的80端口。

    当然Varnish也可以定义多台后端服务器实现负载均衡的目的。

    .connect_timeout定义的是等待连接后端的时间

    .first_byte_timeout定义的是等待从backend传输过来的第一个字节的时间

    .between_bytes_timeout 定义的是两个字节的间隔时间

    当然还可以增加一个backend,用于访问本机的8090端口,假设通过该端口提供图片服务。

     

    
    
    1. backend img {  
    2. .host = "127.0.0.1";  
    3. .port = "8090";  
    4. }  

     

    当匹配img的URL时,需把请求发送到上面定义的backend img,其他的请求发送到backend webserver。
    
    
    1. sub vcl_recv {  
    2. if (req.url ~ "^/img/") {  
    3. set req.backend = img;  
    4. } else {  
    5. set req.backend = webserver.  
    6. }  
    7. }  

     

    Varnish不仅仅可以定义多个backend,还可以把多个backend合成一个组,使用循环的方式把请求分配给组中的backends。并且Varnish会根据健康检查情况来判断后端服务器是否正常提供服务。

    Varnish使用区域语言VCL来管理定义Varnish的存取策略。VCL语法简单,跟Perl比较相似,可以使用多种运算符如"="、"=="、"!,&&,!!"等形式;也可以使用正则表达式来进行匹配,还可以使用"set"来指定变量。当执行VCL时,Varnish会先把VCL转换成二进制代码。

    有一点要注意,""字符在VCL里没有什么特别的含义,这点和其他语言不同。另外,VCL只是配置语言,并不是真正的编程语言,所以没有循环和自定义变量。

    为了可以更好地对Varnish进行配置调整,需要了解Varnish的配置语法,也就是VCL语言。下面对VCL常用的一些函数和变量进行介绍。

    (1)vcl_recv模块

    用于接收和处理请求。当请求成功被调用后,Varnish通过判断请求的数据来决定如何处理请求。此模块一般以如下几个关键字结束。

    pass:表示进入pass模式,把请求交给vcl_pass模块处理。

    pipe:表示进入pipe模式,把请求交给vcl_pipe模块处理。

    error code [reason]:表示把错误标识返回给客户端,并放弃处理该请求。错误标识包括200、405等。"reason"是对错误的提示信息。

    (2)vcl_pipe模块

    此模块在请求进入pipe模式时被调用,用于将请求直接传递至后端主机,在请求和返回的内容没有改变的情况下,也就是在当前连接未关闭时,服务器将不变的内容返回给客户端,直到该连接被关闭。

    (3)vcl_pass模块

    此模块表示当请求被pass后,用于将请求直接传递至后端应用服务器。后端应用服务器在接收请求后将数据发送给客户端,但不进行任何数据的缓存,在当前连接下每次都返回最新的内容。

    (4)lookup

     

    一个请求在vcl_recv中被lookup后,Varnish将在缓存中提取数据。如果缓存中有相应的数据,就把控制权交给vcl_hit模块;如果缓存中没有相应的数据,请求将被设置为pass并将其交给vcl_miss模块。

    (5)vcl_hit模块

    执行lookup指令后,Varnish在缓存中找到请求的内容后将自动调用该模块。

    在此模块中,deliver表示将找到的数据发送给客户端,并把控制权交给vcl_deliver模块。

    (6)vcl_miss模块

    执行lookup后,Varnish在缓存中没有找到请求的内容时会自动调用该方法。此模块可以用于判断是否需要从后端服务器获取内容。

    在此模块中,fetch表示从后端获取请求的数据,并把控制权交给vcl_fetch模块。

    (7)vcl_fetch模块

    在后端主机更新缓存并且获取内容后调用该方法,接着,通过判断获取的内容来决定是将内容放入缓存,还是直接返回给客户端。

    (8)vcl_deliver模块

    当一个没有被缓存的数据交付给客户端的时候被调用。

    (9)vcl_timeout 模块

    在缓存数据到期前调用此模块。

    在此模块中,discard表示从缓存中清除到期数据。

    (10)vcl_discard模块

    在缓存数据到期后或缓存空间不够时,自动调用该模块。

    在此模块中keep表示将数据继续保留在缓存中。

    
    
    1. acl purge {  
    2.        "localhost";  
    3.        "127.0.0.1";  
    4.        "18.81.12.10";  
    5. }  
    6.  
    7.  
    8.        if (req.request == "PURGE") {  
    9.                if (!client.ip ~ purge) {  
    10.                        error 405 "Not allowed.";  
    11.                }  
    12.                return(lookup);  
    13.        }  



    这两个规则定义了允许哪些主机通过HTTP来执行PURG进行缓存删除。如果不是指定的IP,就会出现HTTP 405错误,提示Not allowed错误字样。
    
    
    1. if (req.http.host ~ "^(read)?.aaa.com$") {  
    2.              set req.backend = webserver;   
    3.              if (req.request != "GET" && req.request != "HEAD") {  
    4.                      return(pipe);  
    5.              }  
    6.              else {  
    7.                      return(lookup);  
    8.              }  
    9.      }  
    10.      else {  
    11.              error 404 " Cache Server";   
    12.              return(lookup);  
    13.      }  

     

    这段条件判断用于对aaa.com域名进行缓存加速,aaa.com是泛指概念,也就是说所有以aaa.com结尾的域名都进行缓存。而if (req.request != "GET" && req.request != "HEAD") 表示"如果请求的类型不是GET与HEAD",则返回错误码404。
    
    
    1. if (req.url ~ "^/images") {  
    2.   unset req.http.cookie;  
    3.  }  

    这条规则的意思是清除服务器上/images目录下的所有缓存,当这个请求在后端服务器生效时,如果访问的URL匹配这个规则,那么头信息中的cookie就会被删除。

     

    
    
    1. if (req.request == "GET" && req.url ~ ". (png|swf|txt|png|gif|jpg|css|js|htm| html)$") {  
    2.   unset req.http.cookie;  
    3.  }  
    4.  
    5.  
    6. if (req.http.x-forwarded-for) {   
    7.         set reqreq.http.X-Forwarded-For =   
    8.                 req.http.X-Forwarded-For ", " client.ip; }   
    9. else { set req.http.X-Forwarded-For = client.ip; }  

     

     

    因为Squid、Varnish都会把客户端的IP地址放在HTTP_X_FORWARDED_FOR里面传给后端的Web服务器,所以后端的Web程序都要对其进行调用。
    
    
    1. if (req.request != "GET" &&  
    2.     req.request != "HEAD" &&  
    3.     req.request != "PUT" &&  
    4.     req.request != "POST" &&  
    5.     req.request != "TRACE" &&  
    6.     req.request != "OPTIONS" &&  
    7.     req.request != "DELETE") {  
    8.   return (pipe);  
    9.  }  

     

    该if判断表示如果请求的类型不是GET、HEAD、PUT、POST、TRACE、OPTIONS、DELETE时,则进入pipe模式。注意这里的"&&"是与的关系。
    
    
    1. if (req.request == "GET" && req.url ~ ". (png|swf|txt|png|gif|jpg|css|js|htm| html)") {  
    2.                set beresp.ttl = 180s;  
    3.        }  
    4.        else {  
    5.                set beresp.ttl = 30d;  
    6.        }  
    7.         return (deliver);  
    8. }  

     

    该if判断用于对请求类型是GET,并且请求的URL以png、swf、txt、gif、css、js等结尾时,则进行缓存,缓存时间为180秒。其他缓存为30天。
    
    
    1. sub vcl_deliver {  
    2.  set resp.http.x-hits = obj.hits ;  
    3.  if (obj.hits > 0) {  
    4.   set resp.http.X-Cache = "HIT read.easouu.com";  
    5.  }  
    6.  else {  
    7.       set resp.http.X-Cache = "MISS read.easou.com";  
    8.  }  

     

    这个模块定义的是添加一个Header标识,以判断缓存是否命中。
    
    
    1. sub vcl_error {  
    2.  set obj.http.Content-Type = "text/html; charset=utf-8";  
    3.  synthetic {"  
    4. <?xml version="1.0" encoding="utf-8"?> 
    5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict// EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd"> 
    6. <html> 
    7.    <head> 
    8.       <title>"} obj.status " " obj.response {"</title> 
    9.    </head> 
    10.    <body> 
    11.       <h1>Error "} obj.status " " obj.response {"</h1> 
    12.       <p>"} obj.response {"</p> 
    13.       <h3>Guru Meditation:</h3> 
    14.       <p>XID: "} req.xid {"</p> 
    15.       <hr> 
    16.       <address> 
    17.          <a href="http://read.easou.com/">read.easou.com</a> 
    18.       </address> 
    19.    </body> 
    20. </html> 
    21. "};  
    22.  return (deliver);  
    23. }  

    最后这个模块定义了访问错误页面时的返回信息。

    现在varnish配置基本完成,可以在8080端口上启动varnish,并进行一些基本的测试。

     

    Varnish缓存的配置

    简单的配置文件内容如下:

    
    
      1. backend webserver {    
      2. .host = "127.0.0.1";    
      3. .port = "8090";    
      4. .connect_timeout = 4s;    
      5. .first_byte_timeout = 5s;    
      6. .between_bytes_timeout = 20s;    
      7. }    
      8. acl purge {    
      9.        "localhost";    
      10.        "127.0.0.1";    
      11.        "18.81.12.10";    
      12. }    
      13.    
      14. sub vcl_recv {    
      15.    
      16.        if (req.request == "PURGE") {    
      17.                if (!client.ip ~ purge) {    
      18.                        error 405 "Not allowed.";    
      19.                }    
      20.                return(lookup);    
      21.        }    
      22.    
      23.        if (req.http.host ~ "^(read)?.easou.com$") {    
      24.                set req.backend = webserver;     
      25.                if (req.request != "GET" && req.request != "HEAD") {    
      26.                        return(pipe);    
      27.                }    
      28.                else {    
      29.                        return(lookup);    
      30.                }    
      31.        }    
      32.        else {    
      33.                error 404 " Cache Server";     
      34.                return(lookup);    
      35.        }    
      36.    
      37.  if (req.request == "GET" && req.url ~ ".(png|swf|txt|png|gif|jpg|css|js| htm|html)$") {    
      38.   unset req.http.cookie;    
      39.  }    
      40.    
      41.  if (req.url ~ "^/images") {    
      42.   unset req.http.cookie;    
      43.  }    
      44.    
      45.      if (req.http.Cache-Control ~ "(no-cache|max-age=0)") {    
      46.         purge_url(req.url);     
      47.      }     
      48.      return (lookup);    
      49.    
      50. if (req.http.x-forwarded-for) {     
      51.         set reqreq.http.X-Forwarded-For =     
      52.                 req.http.X-Forwarded-For ", " client.ip; }     
      53. else { set req.http.X-Forwarded-For = client.ip; }    
      54.    
      55.    
      56. if (req.request != "GET" &&    
      57.     req.request != "HEAD" &&    
      58.     req.request != "PUT" &&    
      59.     req.request != "POST" &&    
      60.     req.request != "TRACE" &&    
      61.     req.request != "OPTIONS" &&    
      62.     req.request != "DELETE") {    
      63.   return (pipe);    
      64.  }    
      65.    
      66.  if (req.request != "GET" && req.request != "HEAD") {    
      67.   return (pass);    
      68.  }     
      69.    
      70.  if (req.http.Authorization || req.http.Cookie) {    
      71.   return (pass);    
      72.  }    
      73. }    
      74.  sub vcl_pipe {    
      75.       # set req.http.connection = "close";    
      76.      return (pipe);}    
      77.  sub vcl_hit {    
      78.  if (!obj.cacheable) {    
      79.   return (pass);    
      80.  }    
      81.  if (req.request == "PURGE") {    
      82.          set obj.ttl = 0s;    
      83.          error 200 "Purged.";    
      84.       }    
      85.  return (deliver);    
      86. }    
      87.    
      88. sub vcl_miss {    
      89.  return (fetch);    
      90. }    
      91.    
      92.    
      93. sub vcl_fetch {    
      94.    
      95. if (!beresp.cacheable) {    
      96.  return (pass);    
      97.  }    
      98.  if (beresp.http.Set-Cookie) {    
      99.   return (pass);    
      100.  }    
      101.    
      102.  if (beresp.http.Pragma ~ "no-cache" ||    
      103.      beresp.http.Cache-Control ~ "no-cache" ||    
      104.             beresp.http.Cache-Control ~ "private") {    
      105.   return (pass);    
      106.       }    
      107.    
      108. if (req.url ~ "^/cover/") {    
      109.                set beresp.ttl = 1800s;    
      110.        }    
      111.        else {    
      112.                set beresp.ttl = 30d;    
      113.        }    
      114.          return (deliver);    
      115.    
      116.           
      117. #       if (req.request == "GET" && req.url ~ ".(png|swf|txt|png|gif|jpg|css|js| htm|html|jsp)") {    
      118. #               set beresp.ttl = 180s;    
      119. #       }    
      120. #       else {    
      121. #               set beresp.ttl = 30d;    
      122. #       }    
      123. #        return (deliver);    
      124. }    
      125.    
      126. sub vcl_deliver {    
      127.  set resp.http.x-hits = obj.hits ;    
      128.  if (obj.hits > 0) {    
      129.   set resp.http.X-Cache = "HIT read.easouu.com";    
      130.  }    
      131.  else {    
      132.       set resp.http.X-Cache = "MISS read.easou.com";    
      133.  }    
      134. }    
      135. sub vcl_error {    
      136.  set obj.http.Content-Type = "text/html; charset=utf-8";    
      137.  synthetic {"    
      138. <?xml version="1.0" encoding="utf-8"?>   
      139. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd">   
      140. <html>   
      141.    <head>   
      142.       <title>"} obj.status " " obj.response {"</title>   
      143.    </head>   
      144.    <body>   
      145.       <h1>Error "} obj.status " " obj.response {"</h1>   
      146.       <p>"} obj.response {"</p>   
      147.       <h3>Guru Meditation:</h3>   
      148.       <p>XID: "} req.xid {"</p>   
      149.       <hr>   
      150.       <address>   
      151.          <a href="http://read.easou.com/">read.easou.com</a>   
      152.       </address>   
      153.    </body>   
      154. </html>   
      155. "};    
      156.  return (deliver);    
      157. }    

      Varnish 简介

      Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,varnish 具有性能更高、速度更快、管理更加方便等诸多优点,很多大型的网站都开始尝试使用 varnish 来替换 squid,这些都促进 varnish 迅速发展起来。

      挪威的最大的在线报纸 Verdens Gang(vg.no) 使用 3 台 Varnish 代替了原来的 12 台 Squid,性能比以前更好,这是 Varnish 最成功的应用案例。

       

      Varnish 文件缓存的工作流程

      Varnish 与一般服务器软件类似,分为 master 进程和 child 进程。Master 进程读入存储配置文件,调用合适的存储类型,然后创建 / 读入相应大小的缓存文件,接着 master 初始化管理该存储空间的结构体,然后 fork 并监控 child 进程。Child 进程在主线程的初始化的过程中,将前面打开的存储文件整个 mmap 到内存中,此时创建并初始化空闲结构体,挂到存储管理结构体,以待分配。Child 进程分配若干线程进行工作,主要包括一些管理线程和很多 worker 线程。

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

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

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

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


       
     





    God has given me a gift. Only one. I am the most complete fighter in the world. My whole life, I have trained. I must prove I am worthy of someting. rocky_24
  • 相关阅读:
    Intellij IDEA创建Maven Web项目<转>
    Spring事件监听Demo
    maven打包源码<转>
    枚举类转成json
    Java多线程编程中Future模式的详解<转>
    细数JDK里的设计模式<转>
    设计模式-观察者模式(下)<转>
    Sqlserver自定义函数Function
    sqlSQL2008如何创建定时作业
    JSON 序列化和反序列化——JavaScriptSerializer实现
  • 原文地址:https://www.cnblogs.com/rocky24/p/4813478.html
Copyright © 2020-2023  润新知