零玖博客

nginx 之 proxy_pass 域名 dns 解析问题

在使用 Nginx 作为反向代理服务器时,经常会遇到需要将请求转发给其他服务器的情况。在 Nginx 配置中,proxy_pass 指令是用于指定请求转发目标的关键指令。然而,有时候你可能会遇到与目标服务器的 DNS 解析相关的问题,尤其是当 proxy_pass 中指定的是一个域名而不是 IP 地址时。

比如在 Nginx 的错误日志中可能会看到类似于 "upstream timed out (Connection timed out)" 的错误信息。这意味着 Nginx 在尝试与上游服务器建立连接时超时了。这可能是因为 Nginx 无法解析指定的域名,因此无法确定上游服务器的 IP 地址,

当 Nginx 配置中使用 proxy_pass 指定了一个域名时,Nginx 需要进行 DNS 解析以获取该域名对应的 IP 地址,默认情况下会使用本机在/etc/hosts 和/etc/resolve.conf 中配置的主机和 dns 服务器对域名进行解析,但如果 DNS 解析失败或超时,将导致 Nginx 无法连接到上游服务器,还有一种情况是域名解析记录已经发生了变更,但 Nginx 仍请求的之前解析出的服务器 IP,也会出现这个问题,该问题往往出现在主机 IP 不固定或者经常发送变动的情况下,比如有些机房给的是动态 IP,ddns 域名经常发生解析变动,这种情况下,也会影响 Nginx 访问上游服务器。

解决方法

针对这些问题,有几种解决方法可以尝试:

  1. 手动指定 IP 地址: 最直接的解决方法是手动将目标服务器的 IP 地址直接写入 proxy_pass 指令中,而不是使用域名。这样可以避免 DNS 解析的问题,确保 Nginx 能够正确连接到上游服务器,但是不适合上游是 ddns 域名的情况.
    location / {
        proxy_pass http://123.456.789.012; # 替换成上游服务器的实际 IP 地址
    }
    

     

  2. 优化 DNS 解析: 如果仍然希望使用域名进行反代,则需要确保 Nginx 服务器能够正确解析该域名。可以通过以下方式优化 DNS 解析:
    • 使用可靠的 DNS 服务器: 确保 Nginx 服务器使用可靠、稳定的 DNS 服务器进行解析。
    • 缓存 DNS 记录: 可以通过启用 DNS 缓存来减少或者增加 DNS 解析的频率,提高解析速度和稳定性及时效性,可以使用 Nginx 自带的 resolver 指令启用 DNS 缓存。
      resolver <DNS_IP> valid=300s;
      

    其中,resolver 指令的一般语法如下:

    resolver address ... [parameters];

    参数包括:

    address:一个或多个 DNS 服务器的 IP 地址。可以指定多个地址,Nginx 将按顺序尝试这些地址,直到成功解析主机名或达到超时限制。

    parameters:可选的参数,用于配置解析器的行为。这些参数包括:

    valid=time:指定 DNS 解析结果的有效期。解析结果在被缓存了指定的时间后将被视为过期。过期后,Nginx 将重新向 DNS 服务器请求解析该主机名。时间可以是秒 (s) 、分钟 (m) 、小时 (h) 等。例如:valid=300s 表示 DNS 解析结果在被缓存了 300 秒 (5 分钟) 之后将被视为过期。

    ipv6=on|off:指定是否启用 IPv6 解析。默认情况下,Nginx 会尝试解析 IPv6 地址。设置为 off 时禁用 IPv6 解析。

    ipv6=off:禁用 IPv6 解析。

    incomplete=on|off:指定是否在 DNS 服务器未返回所有可用 IP 地址时继续向下一个 DNS 服务器请求。默认情况下,Nginx 会在 DNS 服务器返回部分结果时继续请求其他 DNS 服务器。设置为 off 时,Nginx 将在收到不完整的响应后停止向其他 DNS 服务器请求。

    例如,以下是一个示例配置:

    resolver 8.8.8.8 8.8.4.4 valid=300s ipv6=off;
    

     

    此配置指定 Nginx 使用 Google Public DNS 服务器 (8.8.8.8 和 8.8.4.4) 进行 DNS 解析,并缓存解析结果 5 分钟。 IPv6 解析被禁用。

    指令 resolve 可以在 http 范围内全局设定,也可以在某一个 server 甚至某一个 location 里面单独设定.

  3. 重试机制: 在一些情况下,DNS 解析可能会由于网络问题或 DNS 服务器问题而失败。在 Nginx 配置中,可以配置重试机制,以便在解析失败时进行重试。
    resolver <DNS_IP> valid=300s;
    set $backend "http://example.com";
    location / {
        proxy_pass $backend;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
    }
    

    这种机制在 example.com 对应多个 IP 地址的情况下才能发挥作用。

    当配置 resolver 指令时,Nginx 会向指定的 DNS 服务器请求解析主机名对应的 IP 地址。如果主机名有多个 IP 地址,Nginx 会尝试按顺序连接这些 IP 地址中的一个。如果第一个 IP 地址连接失败,Nginx 会尝试连接下一个 IP 地址,以此类推,直到成功连接或者所有 IP 地址都尝试失败。

    在这种情况下,如果 proxy_next_upstream 指令配置了在遇到错误时跳过当前服务器,那么当 Nginx 无法连接到第一个 IP 地址时,它会尝试连接下一个 IP 地址。这种机制能够增加系统的可靠性,即使其中一个 IP 地址不可用,Nginx 仍然可以尝试连接其他可用的 IP 地址,从而保证服务的持续性。

 

退出移动版