现象
- nginx反向代理了两个服务A和B,其中A是本机,客户端访问正常;另一个B通过proxy_pass转发,地址是亚马逊内部的域名。客户端访问无结果返回,超时。
- 在nginx所在服务器curl B的域名是可以正常访问的。
- 查看nginx日志,error.log中有无法与B服务域名对应的IP地址建立连接的错误日志。
- 重启nginx 解决问题。客户端访问B服务正常。
原因
- nginx在启动时会将域名对应的几个IP地址保存起来,相当于对域名所对应的IP地址配置了负载均衡。
- 亚马逊云上的服务域名对应的的IP地址会变。
- 上述现象中,经nslookup得到现有B的IP地址和错误日志中的IP地址都不相同,所以nginx原来缓存的几个IP地址目前都变了,没有一个IP地址可用,所以无法正常转发。
- 重启nginx后,nginx重新解析域名对应的IP地址,得到可用的IP地址列表,于是转发正常。
解决方法
nginx.conf中增加定时解析域名对应的IP地址的配置,如下:
# DNS server IP address, valid=300s means IP cache expire time, turn off IPv6 lookup
resolver 10.2.0.2 valid=300s ipv6=off;
# DNS resolve time out
resolver_timeout 10s;
# DNS服务器的IP地址通过/etc/resolv.conf得到。
这不是一个完美的解决方案。其实我们应该设置的是域名对应的IP地址的有效时间。而不应该设置DNS服务的IP地址。如果resolver的值变的不可用了呢?为何不能自动调用DNS服务获取域名的IP呢?或许多网卡的情况,nginx无法知道要用哪个resolver?或许nginx跨平台兼容问题?那为什么如果不设置,nginx启动之后却能自动获取到域名对应的IP并缓存呢?
先这样设一下吧,看看能否解决问题。
参考: Nginx with dynamic upstreams