nginx动态资源的缓存策略
传统缓存策略
客户端通过http协议访问nginx(只能处理静态,动态php资源会调用php-pfm)nginx调用php进行处理,php将处理好的结果暂存在memcache,当外部又有相同处理请求时直接通过memcache将结果返回给php再返回给nginx,nginx再返回给客户端。
- 问题所在:nginx特点:高并发,高性能。但是php动态资源请求是由外部的php处理,至于什么时候能处理完成,是由php决定,不由nginx决定。所以,最大的缺点是会造成nginx阻塞。
高速缓存策略
演变过程:要是memcache是在nginx内部,情况就会完全不同。
客户端通过http协议访问nginx(只能处理静态,动态php资源会调用php-pfm)nginx调用php进行处理,php处理完成后将结果返回给nginx,而nginx内部恰好有memcache进行缓存,当有相同请求进来时,nginx就直接可以将结果返回给客户端,明显会有加速的过程,ngingx也不会被阻塞。
memc+scrache
memc-nginx和srcache-nginx模块均为前淘宝工程师agentzh(章亦春)开发。其中memc模块扩展了Nginx标准的memcache模块,增加了set、add、delete等memcache命令,而srcache则是为location增加了透明的基于subrequest的缓存层。两者配合使用,可以实现上一节提到的高效缓存机制。
但是,原生的nginx并不带memc和scrache模块,一般情况下还需要下载两个模块并重新编译nginx。
这里我们就不再重新编译,我们直接使用openresty(自带memc、scrache模块)。
openresty
OpenResty是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
OpenResty 的目标是让你的Web服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
安装
安装主机:server1[172.25.5.1]
openresty可以在其官网openresty.org进行下载,可以直接下载rpm包(不能自己定义模块)。这里为了更能灵活的使用openresty,我选择下载源码宝进行编译安装。
解压完成后,解压包里的内容:
进入bundel目录后,能看到许多的lua模块;
在进入openresty-1.17.8.2/bundle/nginx-1.17.8目录时,就能看到我们熟悉的nginx解压包的内容了,这里是nginx1.17.8版本
[root@server1 nginx-1.17.8]# ls
auto conf configure contrib docs misc README src
[root@server1 nginx-1.17.8]# pwd
/mnt/openresty-1.17.8.2/bundle/nginx-1.17.8
在对openresty进行编译时,直接
./configury
默认安装位置是在/usr/local/openresty。
编译完成后直接使用gmake和gmake install。
安装成功后进入其目录,进入到nginx,我们所有的配置将在此位置。
[root@server1 bundle]# cd /usr/local/openresty/
[root@server1 openresty]# ls
bin COPYRIGHT luajit lualib nginx pod resty.index site
[root@server1 openresty]# cd nginx/
[root@server1 nginx]# ls
client_body_temp conf fastcgi_temp html logs proxy_temp sbin scgi_temp uwsgi_temp
启动方式是和nginx相同:
执行二进制脚本:/usr/local/openresty/nginx/sbin/nginx
也或者可以为openresty添加systemd的启动脚本。
启动后,可以进行访问测试:
配置
安装并启动memcached
- 首先在其他主机安装memcached服务。
安装主机:
server3[172.25.5.3]
server4[172.25.5.4]
直接使用yum源即可安装。
安装完成之后将memcached启动:
● memcached.service - Memcached
Loaded: loaded (/usr/lib/systemd/system/memcached.service; disabled; vendor preset: disabled)
Active: active (running) since Wed 2020-08-19 16:59:10 CST; 3s ago
Main PID: 24579 (memcached)
CGroup: /system.slice/memcached.service
└─24579 /usr/bin/memcached -u memcached -p 11211 -m 64 -c 1024
Aug 19 16:59:10 server3 systemd[1]: Started Memcached.
此服务默认使用的端口为11211端口:
配置nginx(openresty)的反向代理
在http字段中定义负载均衡:
添加参数keepalive 512;保持512个不立即关闭的连接以提高负载均衡的性能。
调用:
location /memc {
internal; ##表示只接受内部访问
memc_connect_timeout 100ms; ##连接超时时间
memc_send_timeout 100ms; ##发送超时时间
memc_read_timeout 100ms; ##读取超时时间
set $memc_key $query_string; ##使用nginx内部的$query_string;
set $memc_exptime 300; ##表示缓存失效的时间
memc_pass memcache; ##memc通过set操作memcache
}
访问逻辑:
location ~ \.php$ {
set $key $uri$args;
srcache_fetch GET /memc $key; ##拦截GET请求(当有数据访问时,进行拦截。通过定义的memc来处理调动memcache均衡器)
srcache_store PUT /memc $key; ##拦截PUT请求(输出拦截)
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi.conf;
}
当所请求的uri以.php结尾时,首先到memcache中查询有没有以$ uri $ args为key的数据,如果有则直接返回;否则,执行location的逻辑,如果返回的http状态码为200,则在输出前以$ uri $ args为key,将输入结果存入memcache。
测试:
为了形成对比,我们先关闭缓存:
在默认发布目录新建php动态页面:
[root@server1 html]# cat index.php
<?php
phpinfo()
?>
打开php-fpm,reload openresty里的nginx。
使用外部主机对index.php其进行压测:
没有使用缓存:
ab -c10 -n 20000 http://172.25.5.1/index.php
结果:
Server Software: openresty/1.17.8.2
Server Hostname: 172.25.5.1
Server Port: 80
Document Path: /index.php
Document Length: 71511 bytes
Concurrency Level: 10
Time taken for tests: 15.710 seconds
Complete requests: 20000
Failed requests: 2097
(Connect: 0, Receive: 0, Length: 2097, Exceptions: 0)
Total transferred: 1433577663 bytes
HTML transferred: 1430217663 bytes
Requests per second: 1273.09 [#/sec] (mean)
Time per request: 7.855 [ms] (mean)
Time per request: 0.785 [ms] (mean, across all concurrent requests)
Transfer rate: 89114.70 [Kbytes/sec] received
使用缓存:
reload nginx后继续进行压测:
结果:
Server Software: openresty/1.17.8.2
Server Hostname: 172.25.5.1
Server Port: 80
Document Path: /index.php
Document Length: 71511 bytes
Concurrency Level: 10
Time taken for tests: 10.637 seconds
Complete requests: 20000
Failed requests: 0
Total transferred: 1434040000 bytes
HTML transferred: 1430220000 bytes
Requests per second: 1880.26 [#/sec] (mean)
Time per request: 5.318 [ms] (mean)
Time per request: 0.532 [ms] (mean, across all concurrent requests)
Transfer rate: 131658.71 [Kbytes/sec] received
将memcache里的监控页面挪到默认发布目录后,可以看到缓存命中情况:
效率明显提高。成功!