Nginx配置DNS缓存
周五的17:27分,一切准备就绪,再过3分钟下班铃声就要响起,马上就要躺在沙发上享受周末时光了。突然,手机上叮叮的短信声此起彼伏,我心头一紧,不会出幺蛾子了吧。打开手机,50多条未读短信映入眼帘,点击一看是大量接口超时的预警信息,被迫加班的周五来了。
事件经过:
1.立即查看应用日志,发现了大量和外部接口交互(通过域名请求)的异常HttpClientErrorException。
2.联系外部系统对接人,将错误日志信息进行同步。
3.因为所有的请求都是通过nginx代理出去的,继续查看nginx的error日志,发现了大量的Connection refused错误,并且上游的ip地址都是同一个A。
4.继续执行ping命令,发现ping A不通,ping 域名可通,但是指向的ip是B。
5.立即对nginx做了reload处理,交易恢复正常。
6.外部系统对接人反馈,域名绑定了多个运营商,其中一家运营商网络断了(ip A),导致了此次事故。
事件原因:
1.外部系统网络故障了,其中一家运营商网络故障,但是其他运营商仍可提供服务。
2.内部系统中nginx代理请求时,请求的域名,但是未进行dns的配置,默认ip的ttl是永久的,仅在nginx启动或者reload的时候才会触发dns查询,重新解析新的ip。
事件总结:
1.督促外部系统对接方保证网络质量,增加预警机制,及时同步异常信息。
2.内部系统进行改造,nginx增加resolver机制,定期刷新dns缓存,遇到异常时能够自动切换可用服务商ip。
Nginx配置DNS缓存:
1.resolver命令属于核心模块ngx_http_core_module,可在http、server、location使用,用法参考官方文档:https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver
Syntax: resolver address ... [valid=time] [ipv4=on|off] [ipv6=on|off] [status_zone=zone];
Default: —
Context: http, server, location
2.nginx中在location中配置dns解析逻辑。
1)若nginx中不配置resolver 命令,proxy_pass中的域名仅在nginx启动或者reload时执行dns查询,且获取到的ip的ttl时间为永久。
2)配置resolver时可指定dns的ip地址,有效时间,是否使用ipv6地址等,下面的含义为向10.48.189.10的dns服务器解析域名,并且缓存时间设置60s,60s内从缓存获取ip,60s后缓存时效,待下一请求时触发执行dns的解析。ipv6=off指过滤掉ipv6的ip(针对自身系统不支持ipv6场景)
3)resolver_timeout 指定dns查询超时时间
4)为要访问的域名设置变量(关键!)
5)proxy_pass使用变量进行访问
location /test {resolver 10.48.189.10 valid=60s ipv6=off;#使用DNS服务器,缓存30秒resolver_timeout 3s;#设置DNS查询超时时间set $test_upstream "api.weixin.qq.com";#使用变量定义域名,必须设置proxy_pass https://$test_upstream;}
3.通过tcpdump抓包完成验证,当触发dns查询时,会看到发往该dns ip服务器的流量。
tcpdump -i any -n host 10.48.189.10 and port 53-i any:包含所有网卡
-n:直接显示源地址和目标地址ip
host:指定目标主机ip
port:指定目标主机端口
17:46:52.233008 IP 10.20.1.10.56782 > 10.48.189.10.domain: 11102+ [1au] A? api.weixin.qq.com. (46)
17:46:52.252963 IP 10.48.189.10.domain > 10.20.1.10.56782: 11102 3/0/1 A 101.91.37.13, A 101.89.47.18, A 101.91.34.103 (94)
