缓存随谈系列之三:动态缓存

作为缓存系列的最后一篇,也是我重点想要介绍的。

  • 缓存随谈系列之一:数据库缓存
  • 缓存随谈系列之二:静态缓存(使用静态缓存提升网站性能的五种方法)
  • 缓存随谈系列之三:动态缓存

背景是这样的,在两会期间,我们参加了新华社新闻推送方面业务的运维保驾护航。在这方面我们遇到一个很棘手的问题,就是热点类新闻推送,是高并发应用场景,如同电商的秒杀应用。瞬时的热点新闻访问,高并发的场景给数据库缓存及数据库带来了极大的负荷。针对这种场景(采用nginx+php部署的后端应用,前端为手机app客户端),我们采用了动态缓存技术,单机处理能力从50tps提升到5000tps。所以对此技术场景进行了整理,就有了一种想要分享的冲动,本来主要针对动态缓存来进行分享。整理了一下相关的缓存技术,结合数据库缓存、静态缓存(使用静态缓存提升网站性能的五种方法)、动态缓存组成了缓存系列。

何为动态缓存?即对动态页面的缓存。如,对 .do、.jsp、.asp/.aspx、.php、.js(nodejs)等动态页面缓存。可以看出,动态页面一般都会涉及动态计算、数据库缓存、数据库操作,所以每一次访问同一个页面,所获得的数据可能都有所不同。所以如若对数据及时性要求较高的应用,可能不太适合动态缓存。比如,对一个动态页面缓存了半个小时,用户请求访问该动态页面,返回缓存中的数据。很有可能,缓存中的页面数据即半个小时前缓存的页面数据状态。所以,动态缓存,是牺牲数据的及时性换取性能的技术。具体缓存设置多长时间,这个根据业务情况而来。

一、 nginx动态缓存的原理概要

nginx的动态缓存主要通过反向代理(http的负载均衡)实现,所以基本上可以实现所有动态页面的缓存,当然静态页面也能缓存(在上一个系列中已分享过通过nginx实现静态缓存的方式)。
架构原理图如下图1:


缓存随谈系列之三:动态缓存_第1张图片
图1

如上图所示,nginx做负载均衡反向代理,将用户请求转发至后端服务器。我们可以在nginx这层根据规则设置动态/静态缓存,即每次客户请求,直接由nginx将缓存数据返回,而不用再到后端获取响应数据。
Nginx动态缓存核心配置(以缓存jsp为例):

#levels设置目录层次 
#keys_zone设置缓存名字和共享内存大小 
#inactive在指定时间内没人访问则被删除在这里是1天 
#max_size最大缓存空间
proxy_cache_path /alidata/www/default/cache_dir/ levels=1:2  keys_zone=cache_one:200m inactive=1d max_size=30g;
server {
    listen       80;
    server_name  _;
    location /{
           proxy_pass http://10.117.39.67:8080;
           proxy_set_header   Host             $host;
           proxy_set_header   X-Real-IP        $remote_addr;
           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

    location ~ .*\.jsp$
    {
           proxy_cache cache_one;                    # keys_zone后的内容对应
           proxy_cache_valid  200 304 301 302 10d;   #哪些状态缓存多长时间  
           proxy_cache_valid  any 1d;                #其他的缓存多长时间  
           proxy_cache_key $host$uri$is_args$args;   #通过key来hash,定义KEY的值
          
           proxy_pass http://10.117.39.67:8080;
           proxy_set_header   Host             $host;  
           proxy_set_header   X-Real-IP        $remote_addr;  
           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;  
    } 
   
   access_log  /alidata/nginx/logs/default-cache.log;
}

以上配置在上一篇介绍静态缓存的时候,有看到类似配置。其实对于nginx而言,动态缓存和静态缓存的配置基本一致。唯一的区别就是,静态缓存的location配置中,正则匹配的是静态访问请求。而动态缓存的location配置中,正则匹配的是动态访问请求。

二、 案例一:nginx对jsp的动态缓存

在MyEclipse中,新建一个test的web项目,然后在默认的index.jsp中简单输出测试文字、当前日期 及一张图片。index.jsp测试代码明细:

<%@ page language="java" import="java.util.*,java.text.SimpleDateFormat,java.text.DateFormat" pageEncoding="utf-8"%>



  
    This is test page
    
    
        
    
    
  
  
    This is my JSP page. 
![](eg_tulip.jpg)
<% Date date = new Date(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); out.print("Now the time is :" + df.format(date)); %>

然后我们部署到tomcat中,且前端用nginx做反向代理,部署结构如下图2:


缓存随谈系列之三:动态缓存_第2张图片
图2

为了测试方便,在后端仅部署了一台test tomcat。Nginx反向代理的配置如下:

server {
    listen       80;
    server_name  _;
    location /{
           proxy_pass http://10.117.39.67:8080;
           proxy_set_header   Host             $host;
           proxy_set_header   X-Real-IP        $remote_addr;
           proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
   access_log  /alidata/nginx/logs/default-cache.log;
}

每次刷新浏览器我们可以看到显示的时间都是不一样的(如下图3):

缓存随谈系列之三:动态缓存_第3张图片
图3

然后我们对jsp进行动态缓存,核心配置如下图4:
缓存随谈系列之三:动态缓存_第4张图片
图4

这个时候我们通过浏览器访问对应jsp的页面,我们可以看到每次访问,页面显示的时间是一模一样的,由此可见我们nginx的动态缓存功能已经实现。

我们在nginx的服务器中缓存目录可以看到针对刚才访问jsp的缓存文件,直到缓存时间到期,nginx将会一直将存放本地缓存的磁盘文件内容,作为response返回给客户端请求(如下图5):


缓存随谈系列之三:动态缓存_第5张图片
图5

三、 案例二:nginx对php的动态缓存

Nginx 对php的动态缓存,和Nginx对jsp的动态缓存配置基本一致,唯一不同的是才location中匹配php类型即可。由于篇幅有限,nginx对php的缓存就不再细节性的介绍。

四、 php的动态缓存(fastcgi_cache)

除了nginx的动态缓存外,php也有自带缓存(如fastcgi缓存)来实现动态缓存。实现原理架构图如下图6:


缓存随谈系列之三:动态缓存_第6张图片
图6

Nginx的核心配置如下,值得注意的是,这里不需要通过反向代理来设置。是通过FastCGI自带的缓存来实现配置(如下图7):


缓存随谈系列之三:动态缓存_第7张图片
图7

Php的测试代码如下(输出文字、日期及一张图片):
缓存随谈系列之三:动态缓存_第8张图片
图8

通过浏览器多次访问我们的test.php页面,所以看到此页面的内容是不变的:


缓存随谈系列之三:动态缓存_第9张图片
图9

同时我们在服务器中可以看到存放在磁盘中的缓存文件:
缓存随谈系列之三:动态缓存_第10张图片
图10

直接缓存到期,或者我们手动清理缓存文件,则客户端才会收到最新的数据返回,否则将返回本地缓存的数据。

我为自己带盐,原创作者:乔锐杰

你可能感兴趣的:(缓存随谈系列之三:动态缓存)