运维就要无所不能,无所不会
大家好,我是Stanley「史丹利」,你们已经回家我,而我还在学习「其实是因为撞车了,请假计划被打乱了...」。今天聊 nginx 动态dns 解析
。【似乎发现 Nginx 的一个 BUG】
问题排查过程比较长,不感兴趣的朋友可直接跳到文末看结论和 Nginx resolver 的注意点
文章目录如下:
PHP架构核心技术栈是LNMP,业务接口互调的主流方式:
最理想的方案是:方式一,但不同业务之间的接口,跨项目调用并不适用。
所以推荐方案是方式二。但对开发精力投入和codeing有挑战,在公司内部推行难度奇大,尤其初创期的公司基本不可能。光就这点而言,SpringCloud
的统一网关架构ZUUL
或Gateway
确实要比PHP
高明。
个人认为:随着IT互联网不断成熟,小步快跑不断被挑战的,慢就是快理念不断举起的意识下。轻量级PHP语言是否真的快,确实要不断被挑战。前有前端技术语言的快速迭代,纯静态页面逐步成为主流。后面golang新兴高并发语言,Java工程级别架构语言。PHP的定位确实很尴尬,这可能也是PHP市场不断萎缩的原因。吧
剩下的方式三,是我们现在应用比较多的场景。主要以 upstream 和 proxy_pass 为主。
upstream upstream_1 {
ip_hash;
server 10.1.1.1:80 max_fails=3 fail_timeout=31s;
server 10.1.1.2:80 max_fails=3 fail_timeout=31s;
keepalive 10;
}
location /abc/ {
proxy_pass upstream_1;
...
}
如上为目录主流upstream方式
location /out_ip/ {
out_ip.example.com;
}
该方式是nginx proxy
和 ResetFul
结合的“变种”。通常情况下,out_ip.example.com
是作为 ResetFul
的标准接口调用,但少数情况是 out_ip.example.com
同样是 Proxy
角色,后端会有转发或 upstream
到多台Real Server
.
Proxy
最大的问题是:后端Real Server变更时, Nginx 不会主动更新DNS缓存,很不幸,我们还因此引发了一场小事故(对方变更,未通知我们重启nginx)。
官网原文如下:
As NGINX starts up or reloads its configuration, it queries a DNS server to resolve backends.example.com. The DNS server returns the list of three backends discussed above, and NGINX uses the default Round Robin algorithm to load balance requests among them. NGINX chooses the DNS server from the OS configuration file /etc/resolv.conf. This method is the least flexible way to do service discovery and has the following additional drawbacks:
server
directive, which we’ll describe in the next section.https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
坑1:会有遗漏通知的情况(我们就遇到了)
坑2:机器太多,麻烦
坑3:耦合性太高,如变更频繁,无法接入,且可能会影响现有应用
声明 resolver 即可,Nginx core模块内置 ,无需新增编译模块。操作简单
// 但我们遇到了惊天“bug”...折腾了1.5天,也没找到原因..
Nginx Resolver
不需要额外编译Nginx,且配置简单。所以我们第一想法是采用该方案。
location /prod-url-test/ {
...
proxy_pass http://$proxy_url;
}
location /prod-url-test/ {
resolver 4.4.4.4 valid=10s;
set $proxy_url "prod-url-test.t1.test.example.com";
proxy_pass http://$proxy_url;
}
但实际测试结果如下:
下面就开始了抓妖怪的曲折道路,因为过程较为曲折,我大致总结为如下几个阶段:
确认没有模糊匹配的域名干扰
grep -iE '域名' /etc/nginx/ -R
一顿操作猛如虎,一看收入250。竟然没定位到问题,有点尴尬..
随后,我增加了如下测试方案:
lst-dns-test.t1.test.example.com
为最大化模拟问题,域名的长短也保持一致。
为排除现有 DNS 潜在的问题,及技术人员响应不及时的情况。同时我自己又搭建了一套 DNS.
最终配置如下
location /lst-dns-test/ {
resolver 6.6.6.6 valid=10s; # 6.6.6.6 为自建DNS
set $proxy_url "lst-dns-test.t1.test.example.com";
proxy_pass http://$proxy_url;
}
经测试,结果如下:
域名 | 结果 | 是否符合预期 |
---|---|---|
lst-dns-test.t1.test.example.com | dns修改后,Nginx无需重启,自动生效 | 完全符合预期 |
prod-url-test.t1.test.example.com | dns修改后,Nginx不重启不生效,重启后概率生效 | 不符合预期 |
至此,严重公司 DNS 服务配置异常。将测试域名 lst-dns-test.t1.test.example.com
在公司DNS做解析,保证所有配置和 prod-url-test.t1.test.example.com
一样后再做测试。结果依旧~~
至此,其实已经不知道怎么办了... 在和晓明沟通后,建议 tcpdump
看 DNS
解析的数据流是怎么流向的,怀疑 DNS
缓存,并做了递归解析。
依旧没有定位到问题,但帮我们了解到 Nginx resolver 的解析数据流:
而有问题的域名,压根没有到我自建的DNS上请求解析.... 难怪使用我自建的DNS一直不生效。但不能解释 使用公司的DNS,为什么必须重启才能生效。
traceroute lst-dns-test.t1.test.example.com
traceroute prod-url-test.t1.test.example.com
traceroute
后,发现2个域名路由不一样,正常的域名只有一跳,不正常的域名要经过两跳。所以,又将终点怀疑到公司网络设备。
请公司网络同学协助后,建议将服务器的 DNS
修改为我自建的 DNS
, 保证环境的纯净性。
采用该方案后,发现问题依旧。。。
至此,彻底凉凉,接下来再搞,只能看源码了。
后来突生一计。将 Nginx 所有的配置,全部清除,只保留有问题的的域名 prod-url-test.t1.test.example.com
发现,竟然正常了,即不用重启 Nginx,修改 DNS
后, Nginx 解析自动生效。
再恢复所有的 Nginx 配置后,发现问题重现....
问题还原
prod-url-test.t1.test.example.com
lst-dns-test.t1.test.example.com
test-compare.t1.test.example.com
同时测试如上3个域名,1:1保持配置一样,只有 prod-url-test.t1.test.example.com
不正常。
Nginx DNS
解析步骤:dns
解析,再使用nginx relover
指定 的dns解
析dns
解析结果覆盖前者nginx resolver
使用自建dns
, nginx server
系统使用集团dns
nginx resolver
和 nginx server
系统 均使用集团dns
nginx resolver
和 nginx server
系统 均使用自建dns
nginx
, prod-url-test.t1.test.example.com
表现的现象均一样)nginx
, prod-url-test.t1.test.example.com
有一定比例失效, 其它域名表现正常(3种技术环境表现的现象均一样)nginx
配置,只保留 prod-url-test.t1.test.example.com
域名。所有测试均正常。符合要求。还原服务器上所有的nginx配置, 再次回到场景1和2的情况。(3种技术环境表现的现象均一样)nginx resolver
存在一定解析失败的概率问题nginx resolver
在配置较复杂的场景下存在配置失效的问题。Nginx resolver
注意点resolver
功能,通过 resolver
这种方式来实现nginx
动态解析代理域名,相当于放弃了upstream
,也就无法使用upstream相关配置功能
,比如回话保持、健康检测等等好的,不说了。我要去取车为国庆生了。最后祝大家假期愉快,一路不堵!