跳转至

Nginx 缓存服务器(番外)动态 upstream


2019-07-09 by dongnan

问题描述

在更新应用镜像(图中的App1)版本后,部分静态资源抛出 502状态码。 先来看下 nginx缓存服务器日志,重点在"Host is unreachable"这里,顺着这个错误信息找到了错误源头,也有了这篇文章。

2019/06/18 09:46:15 [error] 11#11: *2926 connect() failed (113: Host is unreachable) while connecting to upstream, 
client: 10.42.0.101, server: localhost, request: "GET /css/pc/layout.css?v= HTTP/1.1", 
upstream: "http://10.42.200.140:8080/css/pc/layout.css?v=", host: "zongming.net", referrer: "https://zongming.net/"

项目环境

为了讲清楚问题原因,这里需要说明下项目运行环境,这个WEB项目运行在 Rancher容器平台上,项目架构如图(参考 nginx 缓存服务器(上))。

项目基于Docker容器技术,通过jenkins持续集成工具将代码(war包)附加到Tomcat Docker镜像上,最后项目更新上线是通过升级镜像版本完成的。

排错过程

接下来开始排查问题,通过检查nginx配置文件,发现配置文件使用的是主机名demo-web(rancher内部域名)。

配置文件

cat /etc/nginx/conf.d/default.conf

server {

    listen  80;
    server_name localhost;

    location / {
    proxy_pass          http://demo-web:8080;
    proxy_set_header    Host $host:$server_port;
    proxy_set_header    X-Real-IP $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    # cache
    proxy_cache         proxyCache;
    proxy_cache_valid   1d;
    proxy_cache_key     $uri$is_args$args;
    #
    expires    1d;
    }
}

通过检查日志发现,日志中的 upstream服务器IP 10.42.200.140 与现有的 upstream服务器IP并不相同, 说明 upstream服务器运行期间IP地址发生了改变,这也是日志中"Host is unreachable"问题所在。

nslookup demo-web

Server:         169.254.169.250
Address:        169.254.169.250#53

Name:   demo-web.irm.rancher.internal
Address: 10.42.216.46

Nginx DNS缓存机制

默认情况下Nginx的Resolver没有配置,Nginx将使用首次DNS查询获得的IP地址,之后将不会再查询DNS直到下一次重新加载配置(比如nginx -t)。

所以如果一条DNS记录解析在DNS缓存周期内变更,那么由于Nginx DNS缓存机制的存在,Nginx仍会使用旧的IP地址。

也就是说配置文件中所使用的demo-web主机名在其运行期间IP地址发生了改变,最终导致了502错误。

解决方法

知道了病因那么给出的药方就是为 nginx配置动态 upstream,主动对主机名进行DNS解析,配置文件添加 resolver指令,如下:

cat /etc/nginx/conf.d/default.conf

server {

    listen  80;
    server_name localhost;

    # dns
    resolver 169.254.169.250 valid=8s ipv6=off;
    set $upstream_server http://demo-web:8080;

    location / {
    proxy_pass          $upstream_server;
    proxy_set_header    Host $host:$server_port;
    proxy_set_header    X-Real-IP $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    # cache
    proxy_cache         proxyCache;
    proxy_cache_valid   200 206 304 302 7d;
    proxy_cache_key     $uri$is_args$args;
    #
    expires    7d;
    }
}
  • resolver 表示指定的DNS 169.254.169.250,注意这是 rancher环境内部DNS地址。
  • valid=8s 表示覆盖默认TTL(DNS缓存时间),指定TTL为8秒。
  • ipv6=off 表示关闭 IPV6 解析。
  • set 设置变量,并在proxy_pass指令中使用这个变量。

结束

至此 "nginx 动态 upstream" 这篇文章就完成了,本期就到这里,下期再见。

参考

回到页面顶部