今天发现博客的图片都打不开了,看了一下nginx的报错日志,发现代理的路径已经是失效的了,他没有根据域名重新找新的ip。通过deepseek知道,

默认情况下,Nginx 会在启动或配置 reload 时解析一次域名(比如用于 proxy_pass https://example.com),然后将该 IP 固定缓存在内存中,不会定期重新解析,即使 DNS IP 发生变动。

解决办法的话使用resolver

bash
resolver dnsip valid=10s;

location /images/ {
    set $backend_host 后端地址;
    proxy_set_header Host $backend_host;
    proxy_pass http://$backend_host:9000/;

    autoindex off;
    expires 30d;
    access_log off;
}
设置项 作用
resolver 使用/etc/resolv.conf中的本地 DNS
set $backend_host 域名; 触发 proxy_pass 动态域名解析
proxy_set_header Host $backend_host; 保证后端能接收正确的 Host 头
proxy_pass http://$backend_host:9000/; 正确的动态方式,避免写死 IP

坑中之坑

之前按照上面的方案配置,还是不行,找了一大堆原因,想着是不是ipv6的用不了,还是开源版本的Nginx不支持。改了很多种配置,最后通过chatgpt一步一步调试发现。使用变量的反向代理,他不会帮你截取路径而是直接拼接

就是说你原本使用域名直接配置的话假设访问https://s3.hongsw.cn/blog/1.webp实际转发给后端的是http://域名:端口/pic/1.webp这样,这和之前配置想要的结果是一致的。

而后使用变量之后它是直接拼接的,假设访问https://s3.hongsw.cn/blog/1.webp实际转发给后端的是http://域名:端口https://s3.hongsw.cn/blog/1.webp,所以我线上测试才一直失败,以为是DNS解析不生效。

为什么我能察觉到这点,是因为之前error日志没有打印相关错误信息,后面chatgpt的一句话提醒了我把error_log /var/log/nginx/error.log;后面加上debug变成error_log /var/log/nginx/error.log debug;能看到的信息就多了。我也就在那才发现传给后端的路径不是我想象中要的。

具体的话使用这种该法,使用rewrite和正则去截取重写

plain
        location /images/ {
            set $backend "******";
            rewrite ^/images/(.*)$ /$1 break;
            proxy_pass http://$backend:9000;


            autoindex off;
            expires 30d;
            access_log off;
        }