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

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

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

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

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

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

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

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>This is test page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
  <body>
    This is my JSP page. <br>
    ![](eg_tulip.jpg)<br>
    <%
      Date date = new Date(); 
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
      out.print("Now the time is :" + df.format(date));
    %>
  </body>
</html>

然后我们部署到tomcat中,且前端用nginx做反向代理,部署结构如下图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

然后我们对jsp进行动态缓存,核心配置如下图4:
图4

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

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


图5

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

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

四、 php的动态缓存(fastcgi_cache)

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


图6

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


图7

Php的测试代码如下(输出文字、日期及一张图片):
图8

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


图9

同时我们在服务器中可以看到存放在磁盘中的缓存文件:
图10

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,915评论 18 139
  • 转自陈明乾的博客,可能有一定更新。 转原文声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、...
    C86guli阅读 4,722评论 6 72
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,765评论 18 399
  • 这种活法,很是愚蠢。 习惯了自我否定,对一切都不再自信,只想混混度日,但内心其实不甘平庸。 知道自己可悲,但抱歉,...
    浪迹_绝尘阅读 221评论 0 0
  • 微信小程序已经开启了内测,为了更好的备战微信小程序,我们推出了微信小程序的Axure标准控件,大家可以免费去下载使...
    产品大牛阅读 4,966评论 0 4