线上故障实录 - 一大早服务就不可用了?
难得一个周末,一大早还没有睡醒就接到另外一个团队的电话,app 打不开了,所有的数据都没有了,睡意全无,连忙起来看能不能紧急抢救一下,最终发现是一个要害链路的 nginx 配置谬误,导致 nginx 无奈启动,接下来残缺的记录下欢快的周末中,这个不欢快的晚上
<!– more –>
1. 我的项目环境
首先说一下背景,出问题的这个我的项目是我之前参加的,当初由另外的小伙伴负责。这个我的项目应用 nginx 作为反向代理,因为某些业务上的起因,搞了一个香港和大陆之间的专线,上面又有一层的 nginx 进行不同业务的申请转发
后端服务基于 SpringCloud 微服务搭建,通过对立网关对外提供根本的业务服务; 也有局部服务不是通过网关,间接 nginx 转发过来的(比方外部应用的控制台就没有走网关)
大抵的构造如上图,理论有一些区别,至于为什么抉择这种架构设计,与理论的业务场景以及之前遭逢过的一次 ddos 无关,这个与本文主题关系不大,就不具体开展
2. 问题形容
接下来咱们先看一下呈现的情况,经营的小伙伴最早接到反馈,app 上所有的数据都没了,并提供了一个上次呈现这种场景的起因是域名的证书过期
留神,这里有两个要害信息点
- 数据没有 -> 直观反映是不是业务服务跪了导致的
- 证书过期 -> 咱们的域名采纳的是 let’s encrypt 进行证书颁发,只有三个月的有效期,所以也不是不存在这种可能
3. 问题追踪
后面是背景介绍,而后要开始进入正题,起床第一件事,呃并不是关上电脑,而是先关上 appp 看一下是个什么情况,毕竟不能齐全凭经营一说,就开始找问题
app 体现与经营同学形容统一,所有数据也空白,直观的体现就是服务端 gg 了
尝试解决思路
上面的文字绝对简短,基本思路能够参考上面这个图
先从经营同学提供的思路来看一下证书是否过期,间接浏览器输出 app 接口对应的一级域名xxx.com
,后果发现被 302 到另外一个域名,还真的是证书过期,要害是这个也不是刚刚过期,而是过期了五十多天,这个工夫对不上
既然一级域名没法间接查看,那就抉择 app 间接申请接口的域名,来看一下是不是过期了,后果难堪的事件是我不晓得这个二级域名的前缀是啥(为了防止 ddos,咱们之前做的一个计划是随机生成了很多二级域名前缀,而后依据用户的地区进行二级域名的选取),所以只能通过抓包了
找到域名之后(假如为 xxx.a.com
),间接浏览器拜访,毫无意外提醒 ” 无法访问此网络 ”,那这个域名证书是否过期就不好确定了
呈现下面这个体现,自然而然的就是ping xxx.a.com
,能够 ping 通,证实这个域名解析没有问题
简略的从域名上没有找到显著的突破口,接着去确认一下服务是否还在线,登录服务器,jps -l
查看一下以后过程,后果竟然发现竟然没有 zuul
网关过程,难道是网关跪了导致的么,貌似有眉目了,在筹备重启之前,看了一下日志,竟然发现有失常的心跳日志,这特么的就鬼畜了啊,过程都没有,日志还在打;而后审慎的用 top
看了一下服务器过程,zuul
过程还在,不过坑爹的是它竟然是 root 权限启动的;所以我用一般账号执行 jps -l
没有展现。针对这种情况,强烈建议所有的小伙伴,不要用 root 用户在服务器上搞事件
确定服务还在之后,应用 curl http://127.0.0.1:8080/xxx
来发出请求,失常响应,ok,服务没挂,那么问题就呈现在下层
而后登录下层的几个 nginx 服务器,查看对应的 nginx 拜访日志tail -f /var/log/nginx/access.log
,以及异样日志tail -f /var/log/nginx/error.log
,外面有几个之前的 ssl 验证失败的日志,如同也不是导致这个问题的起因
从日志文件上,看不出太多的信息,接着从最上层的 nginx 登程,ping 域名,层层下推,后果发现到了某一台机器之后,ping 了没反馈,而后查看 nginx.conf
配置,起初是狐疑这里是不是被人动过了(尽管说可能性比拟小),这个时候走了弯路,配置上看不出任何问题,而后下意思的查看了一下 nginx 过程ps aux | grep nginx
,后果发现过程不在,起因找到
nginx 过程为什么会忽然没了,这个前面在说
4. 问题 fix
既然发现是因为 nginx 过程不再导致的起因,那就简略了,启动 nginx 就好了,后果发现 nginx 过程死活都起不来,始终提醒 80 端口被占用, nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) but no 80 process can find
遇到下面这个问题,要解决还不简略,找到占用 80 端口的过程,干掉它
netstat -ntulp | grep 80
让人惊讶的是,没有找到任何占用 80 端口的过程
网上搜寻了一下,有不少小伙伴是通过上面这个命令解决的 NGINX BIND() TO 0.0.0.0:80 FAILED (98: ADDRESS ALREADY IN USE) TO 0.0.0.0:80 FAILED (98: ADDRESS ALREADY IN USE)”)
# use fuser to kill process using port 80!
fuser -k 80/tcp
很遗憾的是,应用下面这个命令仍然没有能解决问题;这就很难堪了啊,这个时候只能祭出我的大杀器了 – 重启服务器
reboot
通过短暂的重启之后,再次启动 nginx,嗯,仍然没有解决问题;nginx 竟然死活起不来,这个问题就有点大发了,先解决线上问题让服务可用吧,长期调整了一下转发规定,把这台机器摘掉,操作结束之后服务复原
接下来咱们的问题就是这个 nginx 为啥起不来
这里有一篇文章带来了一些思路 [Fix nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)](https://chrisjean.com/fix-ngi… “Fix nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)”)
这个文章外面次要说的是在配置中,应用如下这种姿态导致端口占用
server {
listen :80;
listen [::]:80;
}
对应提请的解决方案是只保留一个,或者在前面加一个 ipv6 的限定
server {
listen 80;
listen [::]:80 ipv6only=on;
}
# or
server {listen [::]:80;
}
然而我的 nginx 配置中原本就只有一个listen 80
,没有下面两个,讲道理不应该会抵触才对
留神到 nginx.conf
配置文件中有上面这一行
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
难道是 conf.d 目录下的配置中,某个配置文件和最里面的抵触了导致的么,正好这个目录下只有一个配置文件,先干掉它
cd conf.d
mv xxx.conf xxx.conf.bk
nginx
而后发现 nginx 顺利的起来了,通过再次查看,果然是下面这个起因导致的 80 端口抵触,调整一下即可;而后就剩下一个疑难,就这个配置,之前是怎么起来的(可能只有最开始部署这个的同学才晓得了 …)
最初揭晓一下,为啥这个 nginx 过程会挂掉,对于这个起因我也是很忧桑
5. 小结
其实这个问题最初看来还是比较简单的,根本原因在于某个单点的 nginx 跪了,导致整个服务不可用,这也裸露了几个比较严重的缺点
- 单点问题
- 监控缺失(外围链路的过程监控还是比拟重要的,在整个问题的排查中,真没有想到会是 nginx 过程没有的状况)
- 短信要及时看,并揭示给相应的小伙伴(阿里云曾经揭示了,惋惜这条短信是在最初问题修复之后才通知到负责这一块内容的小伙伴,这种预先,也就给咱们排查为啥 nginx 跪了有点帮忙了 ????)
II. 其余
1. 一灰灰 Blog:https://liuyueyi.github.io/he…
一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛
2. 申明
尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢
- 微博地址: 小灰灰 Blog
- QQ:一灰灰 /3302797840
3. 扫描关注
一灰灰 blog