当前位置: 首页 > Linux

Linux:Nginxproxy_pass域名解析导致的故障

时间:2023-04-06 01:48:24 Linux

后台业务架构:部署详情:  两个容器部署在同一台机器上,通过docker-compose编排,通过link链接。故障描述更新一次代码,发现前端可以打开,但是所有接口请求都是502(BadGateWay)故障排查查看前端容器compose_ui_1的日志,如果刷a后没有问题一大波502(BadGateWay)UI,首先反映是compose_api_1跪了,直接去容器里查看日志。容器日志看起来很正常,没有crash,而且这个日志好像从来没有收到过请求,但是很明显我的前端肯定是有访问权限的,感觉很奇怪。把接口拿出来尝试单独访问:独立访问接口的结果还是很残酷的502(BadGateWay),感觉还是不靠谱。是否访问端口或主机错误?在本机打开wireshark抓包确认请求的主机和端口:这样可以保证前端compose_ui_1访问的主机和端口是正确的,准确结果是502(BadGateWay),所以我们只能检查来自compose_api_1。之前也遇到过类似的问题,因为compose_api_1是通过uwsgi部署的pythonflask,使用上总会出现问题,改uwsgi配置后会停一会。现在它正在卷土重来。先判断compose_api_1是不是真的跪了。..不过不要对此抱太大希望。..直接访问后台api接口。..尴尬的。..好像是好人受了委屈。这不对,抓起包裹再看:好像是真的。..然后看容器日志:呃。..好的。..我错了,compose_api_1没跪。那么问题来了。..后端接口没问题,但是前端访问不对,这是什么鬼?有预感是容器的特性导致的问题。我希望不是。.先去compose_ui_1容器抓包分析一下,看整个请求链有没有问题:好像发现了什么猫腻,Flags[R.]表示tcp链接被reset重置了,但是为什么会无缘无故重置呢?看172.17.0.5.8080返回什么,先telnet先问:什么???这非常令人困惑。首先,这个172.17.0.5.8080从哪里来?二是为什么端口被封?突然,我想到了一个很重要的问题:容器如何知道把请求发给谁?前面解释过,两个容器是通过link链接起来的,如下:Google搜索链接工作原理:链接机制通过环境变量提供这些信息,除了db密码之外,这些信息也会通过环境变量提供。Docker将源容器中定义的所有环境变量导入到接收容器中,通过接收容器中的环境变量可以获取连接信息。使用链接机制后,可以通过指定名称与目标容器通信。这实际上是通过在/etc/hosts中加入名称与IP的解析关系来实现的。那么在compose_ui_1中根据指定的名字在/etc/hosts中翻译出具体的ip然后进行通信呢?容器的名称是什么?/etc/hostsroot@e23430ed1ed7:/#cat/etc/hosts127.0.0.1localhost::1localhostip6-localhostip6-loopbackfe00::0ip6-localnetff00::0ip6-mcastprefixff02::1ip6-allnodesff02:对于compose_ui_1:2ip6-allrouters172.17.0.4detectapifc1537d83fdfcompose_api_1172.17.0.3authapiff83f8e3adf2compose_authapi_1172.17.0.3authapi_1ff83f8e3adf2compose_authapi_1172.17.0.3compose_authapi_1ff83f8e3adf2172.17.0.4api_1fc1537d83fdfcompose_api_1172.17.0.4compose_api_1fc1537d83fdf172.17.0.6e23430ed1ed7如果根据资料是真的,那么172.17.0.4:8080就是compose_api_1的地址吧?,先试一下,虽然返回的authproduct是None,但实际上这是一个有效的请求。再看compose_api_1容器的日志:原来基本没运行,为什么前端访问直接502,原因是ui容器发错地址了,那为什么会这样呢?无缘无故抽搐?刚才根据host的记录做了实验,根据其映射地址发起接口请求没有问题:查看compose_ui_1的nginx日志,尴尬。..nginx日志实际上直接连接到标准输出和标准错误。..为了简单起见,我们直接用dockerlogs查看。好像nginx的转发已经不对了,为什么要转发到172.17.0.5,看nginx关于转发的配置:这个detectapi和上面贴的hosts表能找到正确的地址是172.17.0.4吗?不明白为什么要转发到172.17.0.5。会不会是系统的域名解析有误?尼玛这太神奇了。男人的直觉告诉我,nginx有猫腻!重启容器的nginx,但是容器也重启了。..再次访问该页面,一切正常。..查看容器的nginx日志。如果转发成功,应该可以定位到。问题是nginx?故障定位只是nginx为什么会出现这样的错误?不应该的。.好像是nginx内部域名解析缓存的问题。然后查了资料,呵呵,还真有。https://www.zhihu.com/questio...这很尴尬。对这个问题我有点怀疑,请教了一位资深大佬,大佬的回复是:如果域名后跟proxy_pass,nginx启动时会初始化,以后只复用这个值;参考:ngx_http_upstream_init_round_robin如果upstream后面跟着函数proxy_pass,配置会遵循解析和缓存的逻辑;改进措施不是直接proxy_pass真实域名,而是转发给upstream配置;也可以参考刚才的知乎链接处理方案:https://www.zhihu.com/questio...;扩展问题为什么compose_ui_1指定的compose_api_1会报错?如果proxy_pass后面是真正的域名,是真的直接多路复用还是有时间缓存?本来想用gdb来debug这个问题的,结果搞了一天,还是没有反应。不过也有一点收获,就是如何配置nginx支持gdb:1.修改编译配置文件:auto/cc/confngx_compile_opt="-c"改为ngx_compile_opt="-c-g"2../configure,添加编译参数:--with-cc-opt='-O0',避免编译器优化;例如:./configure--prefix=/usr/local/nginx--with-cc-opt='-O0'....如果不是这样,编译器会优化代码,导致一些变量值调试过程中循环打印失败,会报如下错误:valueoptimizedout下面可以看到调试效果:nginxworker进程处理入口:ngx_http_static_handler欢迎各位大神指点交流,QQ讨论群:258498217转载请注明出处:https://segmentfault.com/a/11...