使用 NGINX 进行微程序缓存的好处

【编者按】本文作者为 Owen Garrett,主要介绍使用 nginx 进行微程序缓存的好处,辅之以生动的实例。文章系国内 ITOM 管理平台 OneAPM 编译呈现。

NGINXNGINX Plus 被广泛应用于网站内容缓存,小到个人网站,大到一些世界大型内容分发网站(CDNs),例如 MaxCDN 和 CloudFlare。

微程序缓存通过将动态、非个人化的内容缓存很短的时间,能有效加速这些内容的传递。在本文中,笔者将展示如何利用微程序缓存技术将一个基于 WordPress 的应用程序最高提速400倍。

为什么要缓存内容?

缓存能够一举两得:通过更快地传递内容,缓存可以改善网站性能,同时减轻源服务器的负担。缓存的效率取决于内容的缓存度。这些内容可以存储多长时间,如何检查更新,相同的缓存内容可以发给多少用户?

使用 NGINX 进行微程序缓存的好处

缓存静态内容,例如图片、JavaScript 和 CSS 文件和几乎不变的网页内容是个相当简单的过程。缓存更新的处理方法包括常规暂停条件 Get,如果有必要,还可以用cache-busting技术来替换引用对象的URL。

缓存个人化内容(即通过服务器应用为每位用户定制的内容)几乎不可能,因为服务器对同一资源的每次请求的回复都不相同。服务器端引用(SSI)和页面片段缓存(ESI)等技术可以协助组合网页,但是这些技术很难实行,而且不一定能改善性能。

两者中间是个有趣的待缓存对象:可能会无计划更换,但是并非针对每位用户(或者在客户端通过 JavaScript实现个性化)的动态内容。这类内容的生成代价很高,提供过时版本又会带来新的问题。

适合缓存的动态内容包括:

  • 经常更新的新闻或博客网站的首页,每隔几秒就有新文章发布
  • 最近资讯 RSS
  • 持续整合(CI)或搭建平台的进度页面
  • 库存、进度或筹款计数
  • 彩票开奖结果
  • 日历数据
  • 在客户端呈现的个人化动态内容,例如利用 cookie 数据展示的广告内容或数据(“你好,你的名字”)

动态内容的微程序缓存

微程序缓存是一种缓存技术,将内容缓存1秒左右很短的时间。这意味着网站更新会延迟不到1秒钟,这在很多情况下是可以接受的。

这种短暂缓存能给网站性能带来可察觉的改观吗?来试试看!

测试应用程序

在本次测试中,笔者用的是标准 WordPress 设置,并填充了一些样本内容

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

显然,即便是处理基本内容,WordPress 服务器也存在性能问题:以 ab 为基准时,它一秒钟只能服务5.53个请求:

root@nginx-client:~## ab -c 10 -t 30 -k http://nginx-server/
Requests per second:    5.53 [#/sec] (mean)
Time per request:       1809.260 [ms] (mean)
Time per request:       180.926 [ms] (mean, across all concurrent requests)
Transfer rate:          319.74 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       3
Processing:  1430 1735 259.4   1580    2228
Waiting:      537  683 119.7    624     980
Total:       1430 1735 259.4   1580    2228

测试中,vmstat 显示造成瓶颈的原因是利用 PHP 生成页面的 CPU 消耗(在 cpu 范围的 us 一列,数值为96到98。)

root@nginx-server:/var/www/html## vmstat 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
10  0      0 136076  44944 585920    0    0     0     0  476 1665 96  4  0  0  0
10  0      0 140112  44952 585924    0    0     0     4  506 1773 98  2  0  0  0
10  0      0 136208  44952 585924    0    0     0     0  576 2057 97  3  0  0  0

热门使用量显示,CPU 被10个执行 PHP 解释器的 Apache httpd 进程占用。

这种设置本身就是问题——它限制了网站每秒钟处理请求的数量不能超过5个,很容易遭到 DOS攻击,而通过添加 CPU 来解决这个问题意味着每年的托管费用都要增加1000美元。

利用 NGINX 简化微程序缓存

利用 NGINX 来加速服务只需两步。

第一步: 通过 NGINX 代理服务器

在 WordPress 服务器安装 NGINX 或 NGINX Plus 并进行配置,让它接收访问流量并在内部转发到 WordPress 服务器:

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

NGINX 代理服务器配置比较简单:

server {
    listen external-ip:80;  # External IP address

    location / {
        proxy_http_version 1.1; # Always upgrade to HTTP/1.1
        proxy_set_header Connection ""; # Enable keepalives
        proxy_set_header Accept-Encoding ""; # Optimize encoding
        proxy_pass http://wordpress-upstreams;
    }

    status_zone wordpress; # NGINX Plus status monitoring
}

upstream wordpress-upstreams {
    zone wordpress 128k;
    keepalive 20; # Keepalive pool to upstream

    server localhost:80;
}

笔者还修改了 Apache 配置(监听端口号和虚拟服务器),这样 Apache 就绑定到了 localhost:80。

你可能以为添加额外的代理服务器会对性能造成负面影响,但是实际上性能变化可以忽略不计:

root@nginx-client:~# ab -c 10 -t 30 -k http://nginx-server/
Requests per second:    5.63 [#/sec] (mean)
Time per request:       1774.708 [ms] (mean)
Time per request:       177.471 [ms] (mean, across all concurrent requests)
Transfer rate:          324.44 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       1
Processing:  1423 1709 341.3   1532    2794
Waiting:      554  703 165.0    608    1165
Total:       1423 1709 341.4   1532    2794

在更繁忙的服务器(处理更多并发请求)中,仅靠 NGINX 实现的优化就能带来显著的性能提升

第二步: 启动短期缓存

在服务器配置中只添加了两条指令,NGINX 或 NGINX Plus 就可以缓存所有可缓存的响应。带有 200 OK 状态码的响应只缓存1秒钟。

proxy_cache_path /tmp/cache keys_zone=cache:10m levels=1:2 inactive=600s max_size=100m;

server {
    proxy_cache cache;
    proxy_cache_valid 200 1s;
    ...
}

笔者再次运行基准测试时,看到了性能显著提升:

root@nginx-client:~# ab -c 10 -t 30 -k http://nginx-server/
Complete requests:      18022
Requests per second:    600.73 [#/sec] (mean)
Time per request:       16.646 [ms] (mean)
Time per request:       1.665 [ms] (mean, across all concurrent requests)
Transfer rate:          33374.96 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.5      1      10
Processing:     0   16 141.5      3    2119
Waiting:        0    6  54.6      1     818
Total:          1   17 141.5      4    2121

这是120倍的性能优化,从每秒钟处理5条请求到600条;这听起来太棒了,不过还有个问题。

缓存进展顺利,笔者验证了内容的确是每秒更新的(因此永不过时),但是未曾预料到的情况发生了。你会发现处理时间的标准偏差很大(141.5毫秒)。CPU 使用率还是100%(用 vmstat 测量),热门使用量显示有10个活跃的 httpd 进程。

笔者还从 NGINX Plus 的活动检测控制面板找到进一步的线索。测试前:

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

测试后:

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

控制面板报告显示,NGINX 在测试期间处理了18032条请求(ab 汇报的18022条请求,以及基准在30秒结束时突出的10条请求)。但是,NGINX 转发了150条请求到上游服务器,在缓存内容1秒钟的情况下,这比我们期望的30秒测试应有的请求数多得多。

怎么回事?为什么 CPU 使用率很高,缓存更新比预期数字更大?

这是因为每次缓存条目过期时,NGINX 就会停止使用它。NGINX 将所有请求都转发给上游 WordPress 服务器,直到它收到响应,可以用新内容来缓存。

这导致了 WordPress 服务器收到的请求经常激增到10条。这些请求会占用 CPU,比缓存响应的请求延迟更多,这就解释了测试结果中的高标准差。

用 NGINX 优化微程序缓存

笔者想要的策略很清晰:需要在确保缓存内容最新的情况下,尽可能少地向上游源服务器转发请求。在缓存内容不断更新的前提下,笔者愿意从缓存获取旧的(延后1到2秒)响应。要实现这一目标,需要添加两条指令:

  • proxy_cache_lock ——限制填充缓存的并发尝试数量,这样当一条缓存入口被创建后,对该资源的请求将会在 NGINX 中排队。
  • proxy_cache_use_stale ——配置 NGINX,使它提供旧的(最近缓存的)内容,同时更新缓存入口。

加上之前已经添加的缓存指令,笔者得到如下服务器配置:

server {
    proxy_cache one;
    proxy_cache_lock on;
    proxy_cache_valid 200 1s;
    proxy_cache_use_stale updating;
    ...
}

基准测试结果的变化十分惊人。每秒钟的请求数量从600跳跃到接近2200:

root@nginx-client:~# ab -c 10 -t 30 -n 100000 -k http://nginx-server/
Concurrency Level:      10
Time taken for tests:   30.001 seconds
Complete requests:      65553
Failed requests:        0
Keep-Alive requests:    0
Total transferred:      3728905623 bytes
HTML transferred:       3712974057 bytes
Requests per second:    2185.03 [#/sec] (mean)
Time per request:       4.577 [ms] (mean)
Time per request:       0.458 [ms] (mean, across all concurrent requests)
Transfer rate:          121379.72 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   0.3      1       5
Processing:     1    4   8.1      3     661
Waiting:        0    1   2.6      1     250
Total:          1    5   8.1      4     661

CPU 使用率也低多了(注意 cpu 下面 id 一栏的空闲时间):

root@nginx-server:/var/www/html# vmstat 3
procs -----------memory---------- ---swap-- -----io---- -system--- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs  us sy id wa st
 1  0      0 106512  53192 641116    0    0     0    37 11016 3727 19 45 36  0  0
 1  0      0 105832  53192 641808    0    0     0    68 17116 3521 13 56 31  0  0
 1  0      0 104624  53192 643132    0    0     0    64 14120 4487 15 51 33  0  0

数据传输率(121379.72千字节/秒,或121兆字节每秒)相当于0.97千兆,因此该测试受网络限制。CPU 平均使用率为66%,该服务器的峰值性能应该大概为2185/0.66 = 3300 个请求/秒。

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

另外,关注 ab 报告的连续响应时间(标准偏差只有8.1毫秒),以及操作面板显示的30秒测试中转发给上游服务器的请求数量很少(16):

使用 NGINX 进行微程序缓存的好处
使用 NGINX 进行微程序缓存的好处

为什么只有16条请求?我们知道缓存到1秒钟时会清零,这个更新过程最多需要0.661秒(从 ab 结果来看),因此可以推测,更新频率不会快于每1.66秒一次。在30秒钟的时间之外,只会收到最多18(30/1.66)条请求。

了解更多

本文简单展示了在短时间内缓存动态内容可能带来的好处,以及 NGINX Plus 的活动监测数据在调整和诊断缓存配置时的用处。如果你想在生产环境中使用微程序缓存,笔者建议你创建并测试一个更为复杂的缓存规则,针对更长时间内的微程序缓存动态和静态内容。

NGINX Plus 还有一项缓存清除功能,可以用来迅速清除 NGINX 缓存中的特定内容。如果你想缓存更长时间的内容,可以将该功能编入程序,但是一旦你更改原始内容,就要立即更新该程序。

要想了解更多信息,请查阅以下资源:

本文系 OneAPM 工程师编译呈现。OneAPM Browser Insight 是一个基于真实用户的 Web 前端性能监控平台,能够帮大家定位网站性能瓶颈,网站加速效果可视化;支持浏览器、微信、App 浏览 HTML 和 HTML5 页面。想阅读更多技术文章,请访问 OneAPM 官方技术博客

本文转自 OneAPM 官方博客

原文地址: https://www.nginx.com/blog/benefits-of-microcaching-nginx/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 本文转载自:众成翻译译者:为之漫笔链接:http://www.zcfy.cc/article/22原文:https...
    极乐君阅读 706评论 0 10
  • 第一章 Nginx简介 Nginx是什么 没有听过Nginx?那么一定听过它的“同行”Apache吧!Ngi...
    JokerW阅读 32,636评论 24 1,002
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • 1.简介:  Nginx:engine X ,2002年,开源,商业版 http协议:web服务器(类似于ht...
    尛尛大尹阅读 1,858评论 0 3
  • 为什么我们的时间不够用,因为我们的贪婪把所有的时间全部杀死!因为我们的欲望把所有的计划统统消灭! 一看标题就知道这...
    花园里的皮皮阅读 350评论 0 0