nginx反向代理dns缓存问题

故事是这样的:

我在家里有一台内网服务器,联通宽带有动态的公网IP,所以我配置了DDNS域名,这样公网就可以通过域名访问到家中的内网服务器。
因为联通宽带封禁了常见的80/443端口,所以我在阿里云服务器上配置了nginx做反向代理,但是发现经常502错误,只有重启nginx才能恢复,此时内网服务工作正常。

原因

究其原因,在于nginx反向代理解析DDNS域名时,只会在Nginx启动解析配置文件的时候解析1次,此后就会一直拿着解析到的IP连接upstream。因此,当我的联通公网IP变化后,nginx并不会重新去解析DDNS域名,导致连接一个错误的IP。

反向代理nginx配置文件大概是这样的:

server {
    charset utf-8;

    listen 80;
    server_name a.mysite.com;
    index  index.html index.htm;

    location / {
        proxy_pass http://backend.mysite.com:7001;
        proxy_redirect     off;
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 10M;
        proxy_busy_buffers_size 20M;
        proxy_max_temp_file_size 0;
    }
}

阿里云a.mysite.com反向代理给http://backend.mysite.com:7001,然而backend.mysite.com的IP地址一旦变化就会导致无法连接。

解决方法

我希望每次proxy行为都重新解析IP地址,或者至少可以控制缓存的时间。

要实现这个效果,必须把backend.mysite.com作为变量,这样nginx启动时则不会解析IP,而是运行时解析。

nginx配置文件修改如下:

server {
    charset utf-8;

    listen 80; 
    server_name a.mysite.com;
    index  index.html index.htm;

    resolver 114.114.114.114 valid=1s;
    set $proxy_pass_url http://backend.mysite.com:7001;
    location / {
        proxy_pass $proxy_pass_url;
        proxy_redirect     off;
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 10M;
        proxy_busy_buffers_size 20M;
        proxy_max_temp_file_size 0;
    }
}

每个请求都会动态set变量proxy_pass_url,然后proxy_pass使用变量连接,这样就可以实现每次强制解析IP地址的目的了。

需要配置resolver指定一个dns服务器,并且还可以指定dns结果缓存的时间,我这里为了保证IP更新及时性,所以设置了valid=1秒。

就此问题得以解决。