在线故障备案-凌晨不可用?在一个难得的周末,我一大早还没醒来就接到了另一个团队的电话。app打不开,数据全没了,一点睡意都没有。关键环节的nginx配置错误,导致nginx启动失败。接下来,我将在愉快的周末,完整记录下这个不愉快的早晨1.项目环境首先说说背景,问题项目我之前参与过,现在换个小伙伴负责。本项目使用nginx作为反向代理。由于一些业务原因,在香港和大陆之间架设了一条专线,下面又多了一层nginx,用于不同业务的请求转发。后端服务基于SpringCloud微服务。通过统一网关对外提供基础业务服务;还有一些服务是直接通过nginx而不是网关转发的(比如内部使用的console不使用网关)。大体结构如上图所示,但其实还是有一些区别的。设计结合实际业务场景和之前的一次ddos遭遇。这个和本文主题关系不大,就不细说了。2.问题描述接下来我们来看一下发生的情况。运营小伙伴最先收到反馈,app上的所有数据都没有了,上次出现这种情况的原因是域名的证书过期了。注意有两个没有数据的关键信息点->直观反映业务服务是否跪了。证书过期->我们的域名使用let'sencrypt进行证书颁发,有效期只有三个月,所以这种可能性也不是没有。事情,呃,不是开电脑,而是先打开app,看看是什么情况。毕竟,你不能只根据操作开始寻找问题。App的性能与操作同学的描述一致。gg为了尝试解决思路,下面的文字比较冗长。基本思路可以参考下图。一、从运营同学提供的看证书是否过期的思路,直接在浏览器输入app界面对应的一级域名xxx.com,结果发现是302到另一个域名,真的是证书过期了。关键是这不仅仅是过期,而是过期了50多天。这次不对。既然一级域名不能直接查看,那就选择app直接请求接口的域名,看看有没有过期,尴尬的是不知道这个二级的前缀是什么——一级域名是(为了避免ddos,我们之前做的一个解决方案是随机生成很多二级域名前缀,然后根据用户所在地区选择二级域名),这样就只能通过抓包找到域名(假设为xxx.a.com),直接访问浏览器。不出意外会提示“无法访问此网络”,那么这个域名证书是否过期就不能确定了。出现上述表现。pingxxx.a.com自然是可以ping通的。证明域名解析没有问题。干脆找个域名没有明显突破口,再去确认服务。你还在线吗,登录服务器,jps-l查看当前进程,原来是没有zuul网关进程。难不成门户跪了?是个ghost,没有进程,日志还在运行;然后我用top仔细查看了server进程,zuul进程还在,但诡异的是,它居然是root权限启动的;所以我用普通账户执行它jps-l不显示鉴于这种情况,强烈建议各位小伙伴不要使用root用户在服务器上做事。确认服务还在后,使用curlhttp://127.0.0.1:8080/xxx发送请求,正常响应,ok,服务没有hang,则问题出在上层,然后login到上层的几台nginx服务器查看对应的nginx访问日志tail-f/var/log/nginx/access.log,以及异常日志tail-f/var/log/nginx/error.log,有几个之前ssl验证失败的日志,好像不是这个问题的原因。从日志文件看,信息不多,然后从最上面的nginx开始,ping域名,layer层层往下推,结果到了某台机器后,ping没反应,然后查看了nginx.conf配置。一开始怀疑是不是被人摸过了(虽然可能性比较小),这次走了弯路,配置上看不出有什么问题,然后查看了nginx进程psaux|有意义的grepnginx,发现进程不在。原因是nginx进程突然消失了。4.problemfix既然发现是因为nginx进程不再导致的原因,就说说吧,很简单。只需启动nginx。原来是nginx进程起不来,一直提示80端口被占用。nginx:[emerg]bind()to0.0.0.0:80failed(98:Addressalreadyinuse)butno80processcanfind遇到上述问题时,不好解决。找到占用80端口的进程,kill掉。网络统计-ntulp|grep80奇怪的是,并没有发现有占用80端口的进程,上网一搜。很多小伙伴都是通过下面的命令解决的。NGINXBIND()TO0.0.0.0:80FAILED(98:ADDRESSALREADYINUSE)TO0.0.0.0:80FAILED(98:ADDRESSALREADYINUSE)")#usefusertokill进程使用端口80!fuser-k80/tcp不幸的是,使用上面的命令仍然没有解决问题;这很尴尬,这是时候使出我的大杀器了——重启服务器reboot短暂重启后,再次启动nginx,嗯,问题还是没有解决;nginx活不下去了,这个问题有点大,先解决吧,由于线上的问题让服务可用。暂时调整转发规则,移除本机。操作完成后,服务将恢复。接下来我们的问题就是这个nginx为什么起不来。这是一篇带来一些想法的文章[Fixnginx:[emerg]bind()to[::]:80failed(98:Addressalreadyinuse)](https://chrisjean.com/fix-ngi...《Fixnginx:[emerg]bind()to[::]:80failed(98:Addressalreadyinuse)》)这篇文章主要讲的是在配置中,使用如下姿势导致端口占用服务器{听:80;listen[::]:80;}请求的解决方法是只保留一个,或者增加一个ipv6limitedserver{listen80;listen[::]:80ipv6only=on;}#orserver{listen[::]:80;}但是我的nginx配置里只有一个listen80,没有上面两个应该不会冲突。我注意到在nginx.conf配置文件中有如下一行#Loadmodularconfigurationfilesfromthe/etc/nginx/conf.ddirectory.#Seehttp://nginx.org/en/docs/ngx_core_module.html#include#获取更多信息。include/etc/nginx/conf.d/*.conf;是不是在conf.d目录下的配置中,是不是某个配置文件和最外层的配置文件冲突导致的?正好这个目录下只有一个配置文件。先把它干掉cdconf.dmvxxx.confxxx.conf.bknginx然后发现nginx已经顺利启动了。再次查看,确实是上述原因导致的80端口冲突,调整即可;那么就只剩一题了,就是这个这个配置,之前是怎么起来的(可能只有第一次部署这个的同学才知道。。。)最后再揭秘这个nginx进程为什么会挂掉。我也很担心这个原因。5.总结其实这个到头来,问题似乎比较简单。根本原因是nginx单点宕机,导致整个服务不可用,同时也暴露出几个严重的缺陷。更重要的是,在整个问题的排查中,真没想到会没有nginx进程)短信要及时阅读并提醒给对应的小伙伴(阿里云已经提醒了,可惜这条短信问题最后被修复了之后跟负责这块内容的小伙伴说了,经过这种事件,会不会帮助我们找出nginx跪的原因?)II.其他1.一个灰色的博客:https://liuyueyi.github.io/he...一个灰色的个人博客,里面记录了学习和工作中的所有博文,欢迎大家去浏览2.声明不是和一封信一样好。以上内容纯属一家之言。由于个人能力有限,难免有疏漏和错误,如有发现bug或有更好的建议,欢迎批评指正,感谢微博地址:小灰灰博客QQ:一灰灰/33027978403。扫一扫关注易慧慧博客
