1. nginx默认根据配置的 proxy_cache_key 计算出 KEY(32 位 Hash 值,小写)
  2. 例如:
1. proxy_cache_path /data/test/cache levels=1:2 keys_zone=cache:1024m inactive=86400
2. proxy_cache_key $hostrequest_uri;
  1. 访问:https://www.test.com/test.js,缓存文件名生成即为
1. md5(www.test.com/test.js)=de5a32f1698a16dad49cdcdf877b49f3
  1. 当请求头传递Accept-Encoding:gzip,源站支持gzip压缩后,响应头返回Vary字段,根据标准的 HTTP 协议,服务端(源站)应该在响应头设置 Vary 字段,来显示指定这些影响缓存的头部字段,缓存系统需要支持这种协商机制,对不同的客户端请求返回不同的资源
  2. 此时同一个路径下md5加密会出现多份缓存,不在简单的md5加密$hostrequest_uri值,而是在原来的加密路径值上再做二次md5加密,根据请求头Accept-Encoding值变化拼接生成响应的缓存,也就是说同个路径根据Accept-Encoding请求头传值不一样生成不同的缓存
  3. 例如Accept-Encoding:gzip和Accept-Encoding:空,会产生两份缓存,一份压缩缓存,一份未压缩缓存
  4. 查看nginx源码部分看看具体缓存创建规则是怎么实现的,源站地址
https://github.com/nginx/nginx/blob/master/src/http/ngx_http_file_cache.c#L250

nginx反向代理缓存实现,md5加密规则,gzip压缩问题_vary

nginx反向代理缓存实现,md5加密规则,gzip压缩问题_缓存_02

nginx反向代理缓存实现,md5加密规则,gzip压缩问题_cdn刷新缓存_03

  1. nginx会根据源站返回的Vary字段,匹配对应的Accept-Charset,Accept-Encoding,Accept-Language三个请求头值参与缓存key加密生成
  2. nginx编译安装--with-debug模块可以看到nginx自带的完整打印日志过程ngx_log_debug1
  3. 关键在于源码第1129行
ngx_md5_init(&md5);
ngx_md5_update(&md5, r->cache->main, NGX_HTTP_CACHE_KEY_LEN);

r->cache->main这个初始值是什么,修改源码添加日志输出打印

char hex_main[32] = {0};
ngx_hex_dump(hex_main, r->cache->main, NGX_HTTP_CACHE_KEY_LEN);
ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,"[%s:%d]cache key: %*s", __func__,__LINE__, 32, hex_main);

发现这是一个md5($hostrequest_uri)后16进制字符串

  1. 即md5加密规则为
md5(www.test.com/test.js)=de5a32f1698a16dad49cdcdf877b49f3
de5a32f1698a16dad49cdcdf877b49f3 16进制转2进制b'\xdeZ2\xf1i\x8a\x16\xda\xd4\x9c\xdc\xdf\x87{I\xf3'
拼接accept-encoding:gzip\r\n再md5一次
完整为:
md5(b'\xdeZ2\xf1i\x8a\x16\xda\xd4\x9c\xdc\xdf\x87{I\xf3'accept-encoding:gzip\r\n)
=55fe7ce9a25bdfaa30e94ec053b020e9
或者linux下二进制转序列号
echo -ne "\xde\x5a\x32\xf1\x69\x8a\x16\xda\xd4\x9c\xdc\xdf\x87\x7b\x49\xf3accept-encoding:gzip\r\n" | md5sum