Web 缓存核心技术点需知

RTXLizette 8年前
   <ul>     <li> <p>Web缓存核心技术点需知</p>      <ul>       <li> <p>5.1 HTTP首部控制</p> </li>       <li> <p>5.2 基于新鲜度检测机制:</p> </li>       <li> <p>2.1 特征1:时间局部性</p> </li>       <li> <p>2.2 特征2:空间局部性</p> </li>       <li> <p>2.3 缓存的优点</p> </li>       <li> <p>2.4 哪类数据应该被缓存</p> </li>       <li> <p>2.5 哪类数据可缓存但不应该被缓存</p> </li>       <li> <p>2.6 缓存命中率决定缓存有效性</p> </li>       <li> <p>2.7 缓存数据生命周期</p> </li>       <li> <p>2.8 缓存处理步骤</p> </li>       <li> <p>2.9 缓存和普通数据读取的区别</p> </li>       <li> <p>1. 完整请求流程中缓存设计</p> </li>       <li> <p>2. 缓存特征点</p> </li>       <li> <p>3. 智能DNS解析(CDN)</p> </li>       <li> <p>4. 常见的缓存工具实现</p> </li>       <li> <p>5. 常见缓存控制机制</p> </li>       <li> <p>6. 常见的HTTP首部字段类型</p> </li>      </ul> </li>    </ul>    <h2><strong>Web缓存核心技术点需知</strong></h2>    <p><strong>序:</strong></p>    <p>该文共约9800字(6章),前5章建议阅读时长为8分钟。第6章为知识点整理,可后续检索回顾。 </p>    <p>近些年,互联网基础设备和技术迅猛发展,互联网玩法日新月异,稍不留神就Out。整体网民的素质也在不断提升的同时,对互联网的体验也提出了新的高度和要求,众所周知智能背后意味着复杂,体验好背后也意味着互联网的架构越复杂。利益当先的前提下,最好的优化就是缓存,缓存在整个互联网的发展过程中作用可想而知。尤其在中国如此蹩脚的网络下,南电信北联通,中间坑的都是付费的用户和企业。越来越多的证明表明,网站访问速度越慢,用户流失的越快,要想加快网站访问速度,基于此背景条件下,缓存和反向代理更显的尤为重要。</p>    <h2><strong>1. 完整请求流程中缓存设计</strong></h2>    <p>从互联网起始至今缓存都无处不在,从最前端的用户侧开始到服务器架构设计领域均在缓存的设计。</p>    <p>用户一次完整的访问简易流程图如下:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/156d05ef8a859517e8d2fa6a9adfee00.jpg"></p>    <h3><strong>1.用户端</strong></h3>    <p><strong>系统</strong></p>    <p>基于DNS缓存: 缓解DNS解析压力,提高解析响应速度</p>    <p><strong>浏览器</strong></p>    <p>基于内容缓存: 根据已有规则与服务器交互过程中,非过期文件不再从服务器请求全新内容</p>    <p><strong>DNS(CDN)</strong></p>    <p>基于DNS:基于DNS的智能解析,将用户的请求解析至距离用户最近的CDN缓存服务器,图片,样式等静态和常期不变的资源交由CDN响应,缓解RealServer压力和高峰访问拥塞。</p>    <h3><strong>2.企业端</strong></h3>    <p><strong>硬LB</strong></p>    <p>请求经防火墙过滤后,传递至后端硬LB服务器,再根据不同场景分发至后端 <em>* 软LB*</em></p>    <p><strong>软LB</strong></p>    <p>软LB再次过滤拆分请求,动静分离,静态请求分离至静态集群,动态请求分发至应用集群。</p>    <p><strong>NoSQL(Cache)</strong></p>    <p>NoSQL:Redis,Memcache,ZeroMQ等NoSQL的出现大大缓解了前端直接穿透对数据库和分布式文件集群服务器的压力。静态文件读取方面,Squid,Memcache,Varnish等缓存率理想情况下更高达80%以上。</p>    <p>大型成熟的高可用网站拓扑可参考如下-摘自网络</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/e6e287a541df55ea0db0bf3870dde18e.jpg"></p>    <h2><strong>2. 缓存特征点</strong></h2>    <p>并非所有的数据被缓存或需要缓存,缓存是为了解决20%数据被80%的人频繁访问的问题而生。数据如希望被缓存往往具备变化缓慢的特征。被缓存的数据往往具备如下特性:</p>    <h3><strong>2.1 特征1:时间局部性</strong></h3>    <p>缓存的数据往往被打有时间缀,具有定期失效的特征,过期后会从源服务器检验请求验证是否需要重新拉取数据。</p>    <p>某数据被访问后,该数据往往会再次在短时间内被访问到。</p>    <h3><strong>2.2 特征2:空间局部性</strong></h3>    <p>被访问数据的周边数据被访问的概率会比其它常规数据访问大很多,所以这些访问数据和其它周边有可能被访问的数据通过某种方式集中在一起,以提高数据的被访问速度,减少数据查找时长。</p>    <p>完成这类功能的工具往往称为Cache。</p>    <h3><strong>2.3 缓存的优点</strong></h3>    <p>缓存的优点无需赘述:</p>    <p>1. 节约带宽 </p>    <p>2. 缓存后端服务器请求穿透压力 </p>    <p>3. 降低时延,加速响应</p>    <h3>2.4 哪类数据应该被缓存</h3>    <ol start="1">     <li> <p>热(区)数据:所谓热(区)数据就是指经常被访问到的数据,这类数据被缓存最有价值,缓存命中率高</p> </li>    </ol>    <h3><strong>2.5 哪类数据可缓存但不应该被缓存</strong></h3>    <ol start="1">     <li> <p>用户账号密码信息等数据,该类数据不仅不应该被缓存,反而要被着重保护,这些年发生的撞库,密码破解等恶性事件,往往都是因为用户个人不当心或企业安全意味不足,导致用户敏感信息流失。</p> </li>    </ol>    <h3><strong>2.6 缓存命中率决定缓存有效性</strong></h3>    <p>缓存命中率=hit/(hit+mixx)</p>    <p>hit表示缓存被命中,miss表示没有命中,也就是缓存项中没有对应的资源 </p>    <p>文档命中率:从文档命中的个数进行衡量 </p>    <p>字节命中率:从内容命中的大小(字节)进行衡量</p>    <h3><strong>2.7 缓存数据生命周期</strong></h3>    <p>数据被缓存数并非永久缓存。根据业务所需和服务器容量及用户行为,各类数据会定期被清理。如王宝强离婚事件,据说因此微博缓存用品横向扩展一倍服务器来响应该突发热点事件,但该热点事情结束后这批服务器是需要下架以节约成本,同时因为热点事件的结束,该时期的热点词及缓存数据将不再被缓存以做清理,该类清理往往需要手动清除,而对于静态文件图片,css等文件,则会设置定期清理,总结如下:</p>    <pre>  缓存清理策略:  1. 缓存项过期:缓存资源往往会被设置有效时长,过期自动清理或失效  2. 缓存空间用尽:缓存空间用尽时,会根据LRU(最近最小使用)算法清理缓存  3. 清理策略设置过长过短都不好,过长数据容易陈旧,过短起不到缓存效果  </pre>    <h3><strong>2.8 缓存处理步骤</strong></h3>    <h3><strong>2.9 缓存和普通数据读取的区别</strong></h3>    <p>缓存数据是 <strong>K/V</strong> 数据, <strong>即key/value</strong> ,缓存的存储方式一般是以文件到的MD5码的前某些字符为键,做为存储目录,存储目录一般是 <strong>多级的</strong> , 其值则可能是整个MD5码,也可能时MD5码减去key所用的字符</p>    <p>k/v存储的好处是检索速度速度快,具有幂等性,此处的幂等性指的是, <strong>无论查找多少次所消耗的时间都是一样的</strong> 。</p>    <h2><strong>3. 智能DNS解析(CDN)</strong></h2>    <p>“缓存最好的实现方式莫过于CDN”</p>    <p>各软件缓存功能实则已是用户请求的最后一环,要想尤佳的体验,CDN是无上之选,智能解析可以做到将用户的请求解析到离用户最近的缓存服务器,缓存命中则直接返回给客户端,若不命中,有可能请求离自己最近的缓存服务器,而不是直接请求真实的服务器,因为缓存服务器往往是形成一个网络</p>    <p>对于国内的分裂网络(电信,联通,移动),CDN可以判断用户来自于哪各运营商的网络,解析请求到相应网络的服务器主机,前提时需要提供web服务运营商需要在不同的的电信运营商部署服务器</p>    <p>GSLB:Globle Servive Load Balance 全局服务负载均衡 </p>    <p>部署专用的一台主机,调度用户请求到离用户最近缓存服务器。 </p>    <p>有全局也有就局部负载均衡,局部服务负载均很器作用是调度本地缓存服务器</p>    <h2><strong>4. 常见的缓存工具实现</strong></h2>    <p>squid&varnish</p>    <p>基于http协议提专业的供缓存控制的程序有squid和varnish,squid比较重量级,是个老家伙,不过,老当益壮,而varnish比较轻量,性能和稳定性于squid不相上下</p>    <p>nginx&httpd</p>    <p>nginx和httpd做为提供web服务的程序,同时也提供了简单的缓存功能,一般在条件允许都因该使用专业的缓存控制软件,而不使用自带的缓存功能</p>    <h2><strong>5. 常见缓存控制机制</strong></h2>    <h3><strong>5.1 HTTP首部控制</strong></h3>    <p>过期日期(Expires):</p>    <p>首部格式:Expires:Fri, 20 May 2016 02:03:18 GMT</p>    <pre>  HTTP1.0版本使用的缓存控制,在响应报文加上Expire首部定义资源的有效日期,其定义的时间为绝对时间,此中控制方式会出现时区差产生的问题  </pre>    <p>Cache-Control:</p>    <p>首部格式:Cache-Control: max-age=600</p>    <pre>  HTTP1.1版本才添加的缓存控制机制,其在请求报文或响应报文首部添加一个cache-control的首部,用于定义资源的缓存最大时长,是相对于响应报文首部中的date首部定义的时间。  一般响应报文首部会同时有Expires首部和Cache-control首部  </pre>    <p>Cache-Control首部相关指令:</p>    <pre>  cache-request-directive=no-cache 不接受缓存响应                                  no-store 不缓存在本地                                  max-age  缓存最大有效时长                                         min-fresh           cache-response-directive=public                                   private                                   no-cache                                    no-store                                   must-revalidate                                   max-age          no-cache:可缓存,但用户每次请求都需要先到上游服务器做缓存检验  </pre>    <p>请求报文缓存控制首部</p>    <pre>  用于发送请求报文时,明确提示所请求的服务器自己是否接收缓存数据或只接收哪类数据(这种情况可能无效,因为缓存代理可能时多级的,可能到了第一个缓存服务器就结束了)  </pre>    <p>响应报文缓存控制首部</p>    <pre>  用于发送响应报文时,明确标示响应的数据是属于哪种类型  </pre>    <p>小结: 基于过期时间的缓存控制,只要缓存命中且在有效期内,都将以缓存数据响应用户,否则就请求上游服务器获取资源</p>    <h3><strong>5.2 基于新鲜度检测机制:</strong></h3>    <p>有效性再验证:revalidate</p>    <p>用户第一次请求的资源被缓存之后,当用户再次请求时,缓存服务器会先与后端缓存服务器做缓存有效性校验,就有如下情况:</p>    <p>(1)如果原始内容没有发生改变,则仅响应首部,不响应body部分(响应码304)</p>    <p>(2)如果原始内容发生改变,则正常响应(响应码200)</p>    <p>(3)如果原始内容消失,则响应404</p>    <p>条件式请求首部</p>    <p>If-Modifified-Since:基于原始内容的最近一次修改的时间戳进行验证,如果发生改变,则200响应,否则304响应</p>    <p>If-Unmodified-Since:基于原始内容的最近一次修改的时间戳进行验证,如果没有发生改变,则304响应,否则200响应</p>    <p>If-Match:使用标签(Etag)进行有效性检验,标签吻合,说明内容没有发生改变,以304响应此次的标签可以理解为文件的校验码,只要文件发生改变,则校验码必定发生改变</p>    <p>If-None-Match:使用标签(Etag)进行有效性检验,标签不吻合,则以200正常 </p>    <p>响应,否则以304响应</p>    <pre>  ********小结********  *(1)基于新鲜度检测机制的缓存控制有个缺点,缓存服务器对于客户端的每次请求,都要做有效性验证,这样虽然保证了响应客户端的内容的新鲜度,但也造成了麻烦,所以就有了过期时间控制和新鲜度控制两种控制机制的结合:    *(2)只要缓存没有过期,都以缓存内容响应用户,若缓存过期,则需要向后端服务器做有效性验证,如果原始内容没有发生改变,则继续以缓存内容响应用户,若原始内容发生改变,则取得原始内容先缓存再响应客户端    *(3)其实浏览器也会将内容缓存在本地,用户再次对同一资源请求时,浏览器和缓存服务器之间会基于标签(**Etag**)进行有效性检测,请求的内容没有发生,则由浏览器缓直接响应,否则就以上述的各缓存控制机制给予响应  </pre>    <h2><strong>6. 常见的HTTP首部字段类型</strong></h2>    <ul>     <li> <p>通用首部字段(General Header Fields):请求报文和响应报文两方都会使用的首部;</p> </li>     <li> <p>请求首部字段(Request Header Fields):从客户端向服务器发送请求报文时使用的首部。补充了请求的附加内容,客户端的信息,响应内容相关的优先级等信息。</p> </li>     <li> <p>响应首部字段(Response Header Fields):从服务器向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。</p> </li>     <li> <p>实体首部字段(Entity Header Fields):针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。</p> </li>    </ul>    <p>HTTP常用首部字段预览表</p>    <p>通用首部字段</p>    <table>     <thead>      <tr>       <th>首部字段名</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>Cache-Control</td>       <td>控制缓存的行为</td>      </tr>      <tr>       <td>Connection</td>       <td>逐跳首部,连接的管理</td>      </tr>      <tr>       <td>Date</td>       <td>创建报文的日期时间</td>      </tr>      <tr>       <td>Pragna</td>       <td>报文指令</td>      </tr>      <tr>       <td>Trailer</td>       <td>报文末端的首部一览</td>      </tr>      <tr>       <td>Transfer-Encoding</td>       <td>指定报文主体的传输编码方式</td>      </tr>      <tr>       <td>Upgrade</td>       <td>升级为其他协议</td>      </tr>      <tr>       <td>Via</td>       <td>代理服务器的相关信息</td>      </tr>      <tr>       <td>Warning</td>       <td>错误通知请求首部字段</td>      </tr>     </tbody>    </table>    <p>请求首部字段</p>    <table>     <thead>      <tr>       <th>首部字段名</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>Accept</td>       <td>用户代理可处理的媒体类型</td>      </tr>      <tr>       <td>Accept—Charset</td>       <td>优先的字符集</td>      </tr>      <tr>       <td>Accept-Encoding</td>       <td>优先的内容编码</td>      </tr>      <tr>       <td>Accept-Language</td>       <td>优先的语言(自然语言)</td>      </tr>      <tr>       <td>Authorization</td>       <td>Web认证信息</td>      </tr>      <tr>       <td>Expect</td>       <td>期待服务器的指定行为</td>      </tr>      <tr>       <td>From</td>       <td>用户的电子邮箱地址</td>      </tr>      <tr>       <td>Host</td>       <td>请求资源所在服务器</td>      </tr>      <tr>       <td>if-Match</td>       <td>比较实体标记(ETag)</td>      </tr>      <tr>       <td>if-Modified-Since</td>       <td>比较资源的更新时间</td>      </tr>      <tr>       <td>if-None-Match</td>       <td>比较实体标记(与if-Match相反)</td>      </tr>      <tr>       <td>if-Range</td>       <td>资源为更新时发送实体Byte的范围请求</td>      </tr>      <tr>       <td>if-Unmodified-Since</td>       <td>比较资源的更新时间(与if-Modified-Since相反)</td>      </tr>      <tr>       <td>Max-Forwards</td>       <td>最大传输逐跳数</td>      </tr>      <tr>       <td>Proxy-Authorization</td>       <td>代理服务器要求客户端的认证信息</td>      </tr>      <tr>       <td>Range</td>       <td>实体字节范围请求</td>      </tr>      <tr>       <td>Referer</td>       <td>对请求中的URL的原始获取方法</td>      </tr>      <tr>       <td>TE</td>       <td>传输编码的优先级</td>      </tr>      <tr>       <td>User-Agent</td>       <td>HTTP客户端程序的信息</td>      </tr>     </tbody>    </table>    <p>响应首部字段</p>    <table>     <thead>      <tr>       <th>首部字段名</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>Accept-Ranges</td>       <td>是否接受字节范围请求</td>      </tr>      <tr>       <td>Age</td>       <td>推算资源创建经过时间</td>      </tr>      <tr>       <td>ETag</td>       <td>资源的匹配信息</td>      </tr>      <tr>       <td>Location</td>       <td>令客户端重定向至指定的URL</td>      </tr>      <tr>       <td>Proxy-Authenticate</td>       <td>代理服务器对客户端的认证信息</td>      </tr>      <tr>       <td>Rety-After</td>       <td>对再次发起请求的时机要求</td>      </tr>      <tr>       <td>Server</td>       <td>HTTP服务器的安装信息</td>      </tr>      <tr>       <td>Vary</td>       <td>代理服务器缓存的管理信息</td>      </tr>      <tr>       <td>WWW-Authenticate</td>       <td>服务器对客户端的认证信息</td>      </tr>     </tbody>    </table>    <p>实体首部字段</p>    <table>     <thead>      <tr>       <th>首部字段名</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>Allow</td>       <td>资源科支持的HTTP方法</td>      </tr>      <tr>       <td>Content-Encoding</td>       <td>实体主体适用的编码方式</td>      </tr>      <tr>       <td>Content-Language</td>       <td>实体主体的自然语言</td>      </tr>      <tr>       <td>Content-Length</td>       <td>实体主体的大小(单位:字节)</td>      </tr>      <tr>       <td>Content-Location</td>       <td>替代对资源的URL</td>      </tr>      <tr>       <td>Content-MD5</td>       <td>实体主体的报文摘要</td>      </tr>      <tr>       <td>Content-Range</td>       <td>实体主体的位置范围</td>      </tr>      <tr>       <td>Content-Type</td>       <td>实体主体的媒体类型</td>      </tr>      <tr>       <td>Expires</td>       <td>实体主体过期的日期时间</td>      </tr>      <tr>       <td>Last-Modified</td>       <td>资源的最后修改日期时间</td>      </tr>      <tr>       <td>为Cookie服务的首部字段</td>       <td> </td>      </tr>     </tbody>    </table>    <p>cookie服务首部字段</p>    <table>     <thead>      <tr>       <th>首部字段名</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>Set-Cookie</td>       <td>开始状态管理所有的Cookie信息</td>      </tr>      <tr>       <td>Cookie</td>       <td>服务器接收到的Cookie信息</td>      </tr>     </tbody>    </table>    <p>set-cookie字段属性</p>    <table>     <thead>      <tr>       <th>属性</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>NAME=VALUE</td>       <td>赋予Cookie的名称和其值</td>      </tr>      <tr>       <td>expires=DATE</td>       <td>Cookie的有效期(若不mingque指定则默认为浏览器关闭前为止)</td>      </tr>      <tr>       <td>path=PATH</td>       <td>将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的目录)</td>      </tr>      <tr>       <td>domain=域名</td>       <td>作为Cookie适用对象的域名(若不指定则默认为创建Cookie的服务器的域名)</td>      </tr>      <tr>       <td>Scure</td>       <td>仅在HTTPS安全通信时才会发送Cookie</td>      </tr>      <tr>       <td>HttpOnly</td>       <td>加以限制,使Cookie不能被JavaScript脚本访问</td>      </tr>     </tbody>    </table>    <p style="text-align:center"> </p>    <p> </p>    <p>来自:http://mp.weixin.qq.com/s?__biz=MzIyMDA1MzgyNw==&mid=2651968866&idx=1&sn=25554c31eac32e78664b962412f515de&chksm=8c349d4ebb431458bef22609db7e9e76d33035ad92c31cbb2d201d13ce94bb8203c69ab9fb33&mpshare=1&scene=1&srcid=11132Z9cZpEE3dXRVhzdSCac&from=groupmessage&isappinstalled=0</p>    <p> </p>