导读
通过本文,你将获得这些知识点
-
dubbo的通信逻辑
-
dubbo的缓存刷新逻辑
-
nacos基础的一些问题现象及尝试
-
dubbo的缓存位置
-
nginx相关知识
背景
直接得到的信息:
先描述下背景,公司有一套集群nacos,5个节点,凌晨两点时宕机了一个节点,服务端的生产者和消费者,均出现了报错,但没有持续报错。
服务端有很多个,早上八点开始,其中有几个服务端一直报错:No Provider,九点左右,启动了宕机的nacos宕机节点,服务端恢复正常。
后来通过详细沟通,又得到了一个信息:
早上八点报错的服务端A,调用服务B导致的报错。No Provider是服务B调用C时,C宕机导致的。
重启了C和B之后,错误依然存在。然后重启了nacos宕机节点,恢复正常。
此次事故造成了上游客户的极差体验感,所以需要针对本次事故做复盘,并且找到根因,做好监控,防止后需继续出现该问题。
排查思路&解决问题
问题既然已经解决,那么就根据现象一步步的做分析,找到问题的根因。
目前怀疑对象:nacos集群节点宕机导致。
nacos集群节点宕机问题排查
首先定位宕机原因,发现是由于服务器的磁盘老旧,导致卡死,nacos节点宕机。
不合理的地方:nacos是集群,宕机一个节点导致整个nacos不可用是有问题的。
既然出现这个问题,就先按照预想的怀疑方向,做一个测试,及预备解决方案。
如果是由于nacos宕机一个节点导致的集群不可用,那么就要先做一波简单分析。
nacos5个节点,宕机一个,还有四个可用,如果集群不可用
-
由于宕机一个节点,剩余四个节点选不出主,导致集群不可用
-
宕机节点依然被nginx负载,没有移除节点,导致服务通过nginx直接撞到了不可用节点
如果真的是这个原因,能分析到的可能原因,大概是这样。
简单分析后,准备测试内容
-
环境准备,模拟生产环境,准备三个节点的nacos集群,相同配置的nginx。
-
服务准备,准备两个服务,方便测试和压测。
-
方案准备:
-
nacos自动拉起脚本,保证nacos的高可用,避免再次出现nacos节点宕机6个小时的情况。
-
nginx节点检测,检测到不可用后,直接下线。
-
nacos模式切换带来的风险,AP和CP模式的切换可行性分析
开始测试
-
复现问题
序号 | 场景 | 结果 | 现象 |
1 | nacos集群启动成功后,服务A和B注册到nacos上面,让nacos宕机一个节点,然后再A调用B,观察是否可以成功。 | 调用成功 | 两个服务端,均会输出一条报错,和nacos的链接断开了一下,随后又立即注册上了。 |
2 | nacos集群全部宕机,使用A调用B,观察是否可以成功。 | 调用成功 | 两个服务端,均会持续输出无法连接到nacos,但不影响服务间的调用 |
3 | nacos集群宕机一个节点,生产者持续超时 | 调用失败,但每次均会实际调用 | 输出一条报错,调用时报错timeout,但每次都会实际调用到生产者。 |
4 | nacos集群全部宕机,生产者持续超时 | 调用失败,但每次均会实际调用 | 持续输出nacos无法连接的异常,调用时报错timeout,但每次都会实际调用到生产者。 |
5 | nacos集群宕机一个节点,生产者宕机 | 首次调用失败,后需不会真实调用 | 输出一条报错,首次去调用,即撞墙,后需则不会走到调用这一步,直接报错,No Provider。生产者重启后,服务又会恢复。 |
6 | nacos集群全部宕机,生产者宕机 | 首次调用失败,后需不会真实调用 | 持续输出nacos无法连接的异常,首次调用会报错,撞墙。后需则不会走到调用这一步,直接报错:No Provider。生产者无法重启,集群无法提供注册能力。 |
7 | nacos集群全部宕机,(首先使用同一个nacos启动生产者和消费者,让消费者中有该生产者的服务配置缓存)生产者宕机后,消费者未调用之前,使用其他nacos注册中心启动服务 | 调用成功 | 持续输出nacos无法连接的异常,在生产者使用其他的nacos重启后,消费者依然可以正常调用生产者,且正常响应。 |
8 | nacos集群全部宕机后,网络中断,调用失败后,再次恢复网络 | 调用先失败后成功 | 消费者调用生产者,网络中断时,调用会失败,网络连通后,又会调用成功。 |
9 | nacos集群全部宕机后,把dubbo生成的本地缓存文件全部删除 | 调用成功 | 本地缓存文件,不影响调用。 |
-
总结结果
-
当服务端全部正常启动后,即使nacos集群完全宕机,也不会影响服务端之间的调用。即使网络波动,连通后依然可以调用成功。只有生产者宕机,才会导致No Provider。
-
暂时的网络波动,恢复后,不会影响正常的服务间调用。
-
dubbo生成的本地缓存文件,已经加载到内存中,gc不会回收这块缓存,除非确实不存在,否则这块配置永远在内存中。
-
服务启动后,注册到nacos上面,在nacos服务列表中已经展示的情况下,依然会出现几秒钟(最长要几分钟)的空白期,无法成功调用,报错No Provider。
-
集群全部宕机后,服务是无法启动的,如果服务能启动(在同一个nacos),消费者端会同步更新这份缓存。
dubbo调用一些关键节点
序号 | 类#方法 | 功能说明 |
1 | org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke | 进入这个方法前,还没有构建关于生产者的配置,333行,list方法的调用,用来获取生产者的执行器。 |
2 | org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#list =》 org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#list | 通过这里,获取执行器列表,然后通过执行器列表来进行路由,找到最终执行器。 |
3 | org.apache.dubbo.registry.integration.DynamicDirectory#doList | 路由时,到这里如果没有找到可路由的执行器列表,会直接报异常:No Provider |
总结
通过一系列测试,最终可以确定的是,nacos一个节点宕机,是不会导致服务异常的。本次说nacos集群不稳定,无非是一次甩锅给架构的一次行为而已。
后需通过细节了解
-
并非所有服务出现不可用,nacos集群服务所有的服务端,只有某个服务链在报异常。
-
报异常的服务链,确实有服务宕机的情况产生。
-
后需宕机服务启动后,依然报这个错,随后直接启动了nacos,启动后就不报错了,很有可能是在空白期,还没有达到真实可调用的情况。当nacos启动后,正好空白期过去了,就下了结论认为是nacos的问题。
解决方案
毕竟确实是nacos节点服务出了问题,根据此次事故,来规避以后出现类似事情,真正去保证nacos集群的高可用。
-
nacos做了拉起脚本,每五分钟检测一次nacos的存活,如果nacos宕机,则会执行脚本重新启动nacos。
-
nginx做了端口检测,如果nacos端口超时超过3次,则将该节点下线。
知识点
-
dubbo服务注册到nacos之后,就会拉取一份配置,保存在本地,服务间调用,只会用本地的配置。
-
dubbo会生成一份缓存配置,在用户根目录的.dubbo目录下。linux系统,在/root/.dubbo 或 /home/xxx/.dubbo下。
-
dubbo本地的缓存执行器,不会因为服务的异常或者连接超时等问题而改变或移除,仅当生产者拒绝端口调用,才会将该执行器移除,否则会一直撞墙。
-
移除执行器后的dubbo,除非nacos集群恢复,否则该配置永远无法恢复,即使生产者靠其他方式启动,消费者也不会再调用该接口。
-
同理,如果在dubbo没有移除执行器之间,生产者不管如何宕机,后来即使用其他的nacos注册中心启动成功,消费者依然可以调用生产者,且可正常拿到结果。所以注意生产者切换nacos注册中心时,要注意在nacos集群正常的情况下进行,否则就会导致消费者端一直存在该配置,即使生产者移到其他位置,依然可以调用。