如果你也不知道如何为proxy_pass配置cache

本文讲述了在NGINX中为proxy_pass配置缓存的详细过程,包括proxy_buffering、proxy_temp_path、proxy_cache_path、proxy_cache、proxy_cache_valid、proxy_cache_bypass和proxy_no_cache等关键配置项的使用,旨在解决PHP+Swoole图床服务的数据库压力问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面的话

事情的起因是,目前的工作环境没有图床,so embarrassing…于是决定自己写一个图床吧,花了一点时间,代码写完了,php+swoole+mysql。问题来了,每次访问图片都需要一次数据库查询,这必然导致数据库鸭梨山大。解决的思路就是加缓存,在CDN之前,想在NGINX层加一下缓存。
因为后端是php+swoole,NGINX的配置大概如下

server {
         listen    1706;
         location /  {
             proxy_pass http://127.0.0.1:9606;
         }
 }

通常情况下,对图片类缓存配置大概是

location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
    expires 3d;
}

此时访问后缀是jpg等的文件后,浏览器会做缓存,直到过期或者Disable Cache
那么,proxy_pass下,如何对请求做缓存呢?

p.s. 我的图床git地址 欢迎围观指正

困惑

梯子不好使,就懒得用谷歌了,在度娘的帮助下,也是找到了若干博文,标题也是相当吸睛,感觉马上就可以解决我的问题了,但是尝试无果,一次次失望,忍不住来自灵魂深处的发问:为什么我不行?
以为看个博文就可以解决,偷懒不想看NGINX的document,但是最后还是不得不去翻document,还浪费了大量时间,偷鸡不成蚀把米。学习一项东西最好的就是它的官方文档。
当然,本文也不一定能解决你的问题,望仅此作为一个解决问题的思路。

破局

翻过的博文不再赘述,当问题解决的一刹那,再也不想去看为什么按照之前的博文配置就是不行了,只要记住正确的方式即可,那些解决不了问题的方法,还管他作甚…

话不多说,切入正题。看那些博文也不是一无所获的,起码知道了有个proxy_cache选项配置,是可以解决这个问题的。

  • 打开NGINX的官网
  • 打开document
  • 既然是proxy_cache这个选项,那么先搜索cache试试,发现不行,只有一个ngx_http_memcached_module,显然不是想要的
  • 再搜索proxy,一共四个,挨着点进去,直到ngx_http_proxy_module,嗯,这就是要找的。当时的心情不亚于哥伦布发现新大陆吧,可是给劳资找到了
    • proxy_cache
    • proxy_cache_background_update
    • proxy_cache_bypass
proxy_buffering
Syntax:	proxy_buffering on | off;
Default:	proxy_buffering on;
Context:	http, server, location

原文中提到Enables or disables buffering of responses from the proxied server.也就是说要想NGINX对proxy的response进行缓存,这个选项必须是on的状态。关于缓存的设置详见proxy_buffer_size和proxy_buffers这两个配置项。如果response过大,还可以通过proxy_temp_path配置一个临时文件目录保存那些临时文件,而临时文件的配置选项有两个:proxy_max_temp_file_size和proxy_temp_file_write_size。

proxy_temp_path
Syntax:	proxy_temp_path path [level1 [level2 [level3]]];
Default:	proxy_temp_path proxy_temp;
Context:	http, server, location

设置临时目录的路径,这里最多可以设置3级子目录,在请求量很大的情况下,可以有效的防止单个文件夹下文件过多的情况。
至于要不要把临时文件缓存到临时目录,则是在proxy_cache_path这个选项中配置的。

proxy_cache_path
Syntax:	proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
Default:	—
Context:	http

这个配置项很重要,项目也很多,需要好好看看。至于上面提到的要不要用temp目录,则是通过use_temp_path=on|off来控制的。keys_zone则是指定了用于缓存的zone和大小,这个zone会在proxy_cache里用到。
另外还可以通过proxy_cache_key 设置缓存的key。

proxy_cache
Syntax:	proxy_cache zone | off;
Default:	proxy_cache off;
Context:	http, server, location

zone就是上面proxy_cache_path里定义的keys_zone的name

写到这里,对于基本需求,大部分的配置就这些了,看一下现在的配置

proxy_cache_path /dev/shm/proxy_cache levels=1:2 keys_zone=one:20m inactive=5m max_size=1024m use_temp_path=on;
server {
    listen    1706;

    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 8 8k;
    proxy_temp_path /dev/shm/proxy_tmp 1 2;
    proxy_max_temp_file_size 1024m;
    proxy_temp_file_write_size 16k;
    proxy_cache_key $scheme$proxy_host$request_uri;
    
    location /  {
        proxy_cache one;
        proxy_pass http://127.0.0.1:9606;
        proxy_set_header request_id $request_id;
    }
}

为什么说是大部分呢,因为如果只是这些配置,还不能起到想要的结果,因为默认状态是200的response是不会缓存的! 因为还没有看完ngx_http_proxy_module这块的document,这个结论暂时没有从document里找到出处。发现这个问题是,在以上配置尝试无果后,配置了一个proxy到https://www.baidu.com的location,结果给缓存了,这个code是302。也算阴差阳错了。
要想缓存code是200的response,必须设置proxy_cache_valid。

proxy_cache_valid
Syntax:	proxy_cache_valid [code ...] time;
Default:	—
Context:	http, server, location

如果只设置时间不设置code,则只有code是200, 301以及302的response会缓存。

再加上这个配置项,就大功告成了!
这时候还有一个问题,如果数据更新了,但是缓存还没过期,想要最新的数据怎么办?
这时候需要两个配置项:proxy_cache_bypass和proxy_no_cache

proxy_cache_bypass
Syntax:	proxy_cache_bypass string ...;
Default:	—
Context:	http, server, location

Defines conditions under which the response will not be taken from a cache.

proxy_no_cache
Syntax:	proxy_no_cache string ...;
Default:	—
Context:	http, server, location

Defines conditions under which the response will not be saved to a cache

嗯…暂时还不是很清楚为什么要设置两个功能一样的配置项。实验的结果是,如果只配置了proxy_no_cache,最终并没有跳过缓存,而只配置proxy_cache_bypass是会跳过缓存的,当然两者都配置也是会跳过缓存的。这里要等待后续更深入的研究了

至此,需要的配置算是OK了,最终的配置项

proxy_cache_path /dev/shm/proxy_cache levels=1:2 keys_zone=one:20m inactive=5m max_size=1024m use_temp_path=on;
server {
    listen    1706;
    
    proxy_buffering on;
    proxy_buffer_size 8k;
    proxy_buffers 8 8k;
    proxy_temp_path /dev/shm/proxy_tmp 1 2;
    proxy_max_temp_file_size 1024m;
    proxy_temp_file_write_size 16k;
    proxy_cache_key $scheme$proxy_host$request_uri;
    proxy_cache_valid 5m;
    proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment $http_pragma;

    location /  {
        proxy_cache one;
        proxy_pass http://127.0.0.1:9606;
        proxy_set_header request_id $request_id;
    }
}

尾声

还有一些遗留的困惑需要解决

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值