dongnan
总版主
总版主
  • 粉丝52
  • 发帖数2198
  • 铜币13939枚
  • 威望6046点
  • 银元150个
  • 社区居民
  • 最爱沙发
  • 忠实会员
  • 喜欢达人
  • 原创写手
阅读:78回复:0

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

楼主#
更多 发布于:2019-07-09 18:40
问题描述
在更新应用镜像(图中的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容器技术,通过CI(持续集成)工具将代码(war包)附加到Tomcat Docker镜像上,最后项目更新上线是通过升级镜像版本完成的。


排错过程
1. 接下来开始排查问题,通过检查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;
    }
}

2.通过检查日志发现,日志中的 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

3. 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" 这篇文章就完成了,本期就到这里,下期再见。

公众号
欢迎关注微信公众号: 运维录


参考
Rancher 内部DNS服务
nginx-resolver
Nginx 的动态 upstreams
#
欢迎关注微信公众号: 运维录
游客

返回顶部