静态加速是CDN很主要的一个功能,静态缓存可以大大减少原站服务器的访问压力,提高用户的下载速度并且降低下载延迟。
编译
nginx的第三方模块ngx_cache_purge提供了静态缓存的功能,nginx使用1.18.0版本,编译如下:
git clone https://github.com/FRiCKLE/ngx_cache_purge
cd /worker/opensourcecode/nginx-1.18.0
./configure --add-module=/home/wanghao/worker/opensourcecode/nginx_module/ngx_cache_purge/ --with-debug
make -j 8 && make install
nginx配置文件
user root;
worker_processes 4;
error_log logs/debug.log debug; # 编译中开启了debug,这里可以输出debug日志了
events {
worker_connections 1024;
}
worker_rlimit_core 10g;
working_directory /usr/local/nginx/logs;
http {
#include mime.types;
#default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
# 静态缓存功能必要的配置
proxy_temp_path /data/nginx_cache/proxy_temp;
proxy_cache_path /data/nginx_cache/proxy_cache levels=1:2 keys_zone=cache_one:50m inactive=1d max_size=1g;
proxy_connect_timeout 5;
proxy_read_timeout 60;
proxy_send_timeout 5;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_404;
upstream originserver
{
server 127.0.0.1:8080; # 利用8080端口来模拟原站
}
server {
client_max_body_size 4G;
listen 80;
root /data;
location ~ \.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*) {
proxy_pass http://originserver; #如果没有缓存则通过proxy_pass转向请求
proxy_redirect off;
proxy_set_header Host $host;
proxy_cache cache_one;
proxy_cache_valid 200 302 1h; #对不同的HTTP状态码设置不同的缓存时间,h小时,d天数
proxy_cache_valid 301 1d;
proxy_cache_valid any 1m;
expires 30d;
add_header host "nginx_proxy";
}
#purge插件缓存清理
location ~ /purge(/.*) {
allow 127.0.0.1; #能够清除缓存的服务器IP地址
deny all;
proxy_cache_purge cache_one $1$is_args$args;
}
}
server {
client_max_body_size 4G;
listen 127.0.0.1:8080; # 原站服务器
root /data;
location ~ \.(gif|jpg|png|htm|html|css|js|flv|ico|swf)(.*) {
autoindex on;
autoindex_exact_size on;
autoindex_localtime on;
add_header host "originserver";
}
}
}
静态缓存功能的配置项说明,可以参考 blog.csdn.net/zhangjunli/…
使用curl进行测试
因为原站和nginx缓存服务器都部署再同一台设备上,缓存服务器访问原站是通过127.0.0.1的IP访问的,在测试的时候,你很难知道数据是从原站下载的还是从nginx代理服务器下载的。所以再测试时先对访问127.0.0.1(lo)本地环回口设置200ms的延迟。
tc qdisc add dev lo root netem delay 200ms
此处也可以仅仅对lo口的8080端口设置延迟,但是,没查到如何设置。测试完成后记得要删除tc设置的规则
tc qdisc del dev lo root netem
第一次测试:
# time curl -L -v -H "Connection:close" "http://192.168.116.130:80/333.png" -o 333.png
* Trying 192.168.116.130...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 192.168.116.130 (192.168.116.130) port 80 (#0)
> GET /333.png HTTP/1.1
> Host: 192.168.116.130
> User-Agent: curl/7.58.0
> Accept: */*
> Connection:close
>
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Fri, 04 Sep 2020 12:33:28 GMT
< Content-Type: text/plain
< Content-Length: 1038692
< Connection: close
< Last-Modified: Sun, 16 Aug 2020 03:01:36 GMT
< ETag: "5f38a190-fd964"
< host: originserver
< Expires: Sun, 04 Oct 2020 12:33:28 GMT
< Cache-Control: max-age=2592000
< host: nginx_proxy
< Accept-Ranges: bytes
<
0 1014k 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0{ [15754 bytes data]
100 1014k 100 1014k 0 0 359k 0 0:00:02 0:00:02 --:--:-- 359k
* Closing connection 0
real 0m2.845s # 可以看到花费的时间是2.8秒,很长了
user 0m0.000s
sys 0m0.063s
第一次测试real 0m2.845s 耗时约2.8秒
同步可以看到nginx的debug日志输出 connect to 127.0.0.1:8080,可以得知是代理服务器进行了回源。
2020/09/04 05:24:53 [debug] 15549#0: *2 connect to 127.0.0.1:8080, fd:17 #3
2020/09/04 05:24:53 [debug] 15549#0: accept on 127.0.0.1:8080, ready: 0
与此同时可以看到 /data/nginx_cache/proxy_cache 目录下
root@ubuntu:/data/nginx_cache/proxy_cache# find ./
./
./2
./2/71
./2/71/e6c8034119c0b548126eb2ddcfdef712
第二次测试:
# time curl -L -v -H "Connection:close" "http://192.168.116.130:80/333.png" -o 333.png
* Trying 192.168.116.130...
* TCP_NODELAY set
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 192.168.116.130 (192.168.116.130) port 80 (#0)
> GET /333.png HTTP/1.1
> Host: 192.168.116.130
> User-Agent: curl/7.58.0
> Accept: */*
> Connection:close
>
< HTTP/1.1 200 OK
< Server: nginx/1.18.0
< Date: Fri, 04 Sep 2020 12:40:06 GMT
< Content-Type: text/plain
< Content-Length: 1038692
< Connection: close
< Last-Modified: Sun, 16 Aug 2020 03:01:36 GMT
< ETag: "5f38a190-fd964"
< host: originserver
< Expires: Sun, 04 Oct 2020 12:40:06 GMT
< Cache-Control: max-age=2592000
< host: nginx_proxy
< Accept-Ranges: bytes
<
{ [17236 bytes data]
100 1014k 100 1014k 0 0 45.0M 0 --:--:-- --:--:-- --:--:-- 47.1M
* Closing connection 0
real 0m0.049s # 可以看到时间大大的减少了
user 0m0.016s
sys 0m0.016s
第二次测试可以看到 real 0m0.049s 耗时大大减少了
学习借鉴
1. nginx缓存目录的创建规则
源文件名字是333.png,缓存文件名字是e6c8034119c0b548126eb2ddcfdef712,
在nginx.conf中levels=1:2配置的是2级的目录, 则真实的目录如下:
# find ./
./
./2
./2/71
./2/71/e6c8034119c0b548126eb2ddcfdef712
再仔细看目录是可以看到第一级目录取了最后一个字符,有16种情况,第二级目录取了最后两个字符,有255中情况。
这种根据取hash值的不同位置来创建目录的方法很常用,也很方便。知道原文件名字和哈希算法,就可以拼凑出路径来。
TODO
1. nginx缓存的文件比原始文件大一些
-rw-rw-rw- 1 root root 1038692 Sep 4 20:40 333.png
-rw------- 1 root root 1039322 Sep 4 05:33 ./2/71/e6c8034119c0b548126eb2ddcfdef712
该例子中静态缓存的文件比原始文件大了630个字节,测试了一些其他不同的图片文件,大约都是630字节左右。
通过Beyond Compare功能对比后,发现静态缓存文件是在原文件的头部插入了630个字节,应该是一些缓存文件的信息,后续需要需要阅读源码才能得出这个630个字节的详细信息
2. nginx缓存文件名字的生成规则
源文件名字是333.png,缓存文件名字是e6c8034119c0b548126eb2ddcfdef712,需要阅读源码看下生成文件名的规则。