New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
nacos-client的HostReactor类的 processServiceJson方法中的推空防护机制在dubbo2.7.5应用环境下无法生效 #5163
Comments
serviceInfo.validate中 1.4.1版本添加了空列表判断,可以读一下。 1.2.1确实存在问题, 没有推空保护的功能。 服务端推空一般有2种情况,1. 服务列表确实为空;2. 服务不存在 这两种情况都应该排查为什么服务没了。 如果需要推空保护,就需要升级到至少1.4.1版本客户端,打开推空保护。 |
PS: 1.2.1的代码看起来是默认开启推送保护
可但是,它没有考虑serviceInfo.getHosts().size()==0这种empty,这也是我们目前缓释问题的方法,采用这种缓释方法已经平稳运行了几天了。 |
当 serviceInfo.getHosts().size()==0, !serviceInfo.validate() 为true,所以这个情况是考虑了的 只是和1.2.1相比,namingPushEmptyProtection 默认不是true。需要主动配置一下 namingPushEmptyProtection为true |
namingPushEmptyProtection这个值应该考虑向前兼容,除非有非常紧要的理由,升级了更容易出毛病也不合适。 |
看这一部分
我感觉一般是要向前兼容 |
绕一大圈返回一个false,有啥必要呢? |
我们讨论的是 serviceInfo.getHosts().size()==0 的情况是否考虑进去了。 因此可以不用修改HostReactor,修改一下namingPushEmptyProtection 就可以。 我们只是讨论问题,你觉得实现不优雅,可以另外再讨论。 |
serviceInfo的hosts成员是构造serviceInfo时刻就new出来的,不可能为null,所以在validate方法里增加一行==null判断本身就很奇怪,这个写法和代码是否优雅无关,更像是手误。 |
你这么说,我又看了一下版本和commit
这个 isAllIPs 也不清楚有什么用,感觉可以删了 |
假设服务列表推送json串反序列化出来hosts为null,1.2.1的代码也是有保护,如下: |
从名称上看,pushEmptyProtection这个参数只和服务列表Hosts是否为空相关; |
只是建议,仅供参考。毕竟都只是缓解问题,服务下线、上线为什么会触发nacos-client收到空服务列表的根源还没有找到。
|
其实将validate和推空保护分开也是合理的,但是应该validate在前,我觉得。 另外就是serviceInfo.getHost == null 这点,属于一个保护性的条件,也许是很老的版本里可能返回null的列表而非空列表,为了兼容而存在的逻辑,只是一直没有删除;也可能是就是顺手写一下。我觉得留着比较好,只是可能可以移动到serviceInfo.validate()里 |
最后我看完所有讨论后,感觉您的问题其实已经在1.4.1版本解决了。 所以我认为该issue可以关闭。 大部分讨论其实是在讨论细节应该在哪里处理更优雅和可读性的问题,可以单独开issue讨论。 |
namingPushEmptyProtection这个值默认应该是true吧,1.4.1版本默认是false,用dubbo2.7.5的应用根本就无法配置这个参数,使用nacos-client1.2.1至少在hosts为null时还有推空保护,升到1.4.1之后,情况更糟了。 |
实际上如果hosts为null,1.4.1的nacos-client会直接抛异常,这个是另外一个问题了。 |
namingPushEmptyProtection这个东西要配置也应该是在dubbo.registry下配置吧,我们用的是dubbo2.7.5,我们想配置它也配不了,dubbo 2.7.5的NacosNamingServiceUtils的buildNacosProperties还不认识这个参数。 |
debug显示是从dubbo注解
上面这些都是dubbo2.7.5的类,最后这个createNamingService负责解析URL创建properties,但是它根本就不读取namingPushEmptyProtection配置参数。 |
1.2.1有部分推空保护能力,因为判null在validate()之外!可以阻止hosts=null的推空,下面是1.2.1的半拉子推空保护代码:
下面是1.4.1的推空保护代码,看似完美但在dubbo2.7.5应用环境下没有半点用处,因为pushEmptyProtection恒为false,根本就设置不了。
|
这个问题有两种方式可以处理,1是在nacos client测增加读取JVM或环境变量的方式设置该值。 2是提交给dubbo或SCA等框架,添加类似的入参或设置方式。 我觉得两边都增加都可以。 |
dubbo provider注册到nacos注册中心的处理过程有两步,第1步是构建注册中心的url,这个环节是读取应用配置的注册中心参数,将这些参数作为url的parameter缓存到一个map里;第2步是从缓存的map取出url,根据url的parameter构建nacosNamingService的properties。
无论最终采取哪种方式,都需要nacos和dubbo两个团队支持。 |
可以参考SCA最新的处理方式,除了少量常用和必填的key以外,就只有一个properties,kv都是用户自己配置的,这样可以支持扩展,需要dubbo团队支持。 client这边其实也需要抽象一个properties的getter 所有变量都应该支持从入参-JVM-环境变量这样一个顺序的读取。 |
又看了一遍dubbo 2.7.5的代码,已经有dubbo.registry.parameters这个配置参数了,类型就是hashmap,应用配置的格式就是json串,nacos注册中心的所有参数都可以在这个配置项里配置,构建注册中心url时dubbo直接把这个hashmap里的各个item作为了url的parameter。 |
use nacos-client 1.4.1 with dubbo 2.7.8+
|
用exclude |
明白你们的意思了,修改应用的pom文件,使用高版本dubbo在构造nacosNamingService时使用nacos-client 1.4.1定义的属性类吧,我们的大多数应用目前还不兼容dubbo 2.7.7+,所以短期内还升不了dubbo版本。 |
建议直接删除namingPushEmptyProtection这个参数,看不到这个参数有什么实际用处,在彻底解决nacos-client持续收到空服务列表问题(hosts为null或者hosts.size()==0)之前,这个参数只会加重问题。 |
假设服务真的全没有了,客户端还保存服务列表的副作用无非就是调用失败,出现message can not send, because channel is closed异常,这个结果可以接受吧,反正横竖都是调用失败而已。 |
刚才查看了一台测试环境的nacos注册中心(1.2.1版本,日志开启了DEBUG输出)的naming-server日志,发现有很多基础服务间隔几秒就会出现no instance to serve for service: DEFAULT_GROUP@@x.x.xService。 |
是这样, 所以才有推空保护功能。 但是推空保护和保护阈值一样,是一个修改了实际结果的操作,那么需要用户明知开启了这个操作。 还有一个问题是,客户端不应该在服务端正常及服务列表正常的情况下获取到非法或空列表,如果出现应该排查哪里出了问题,并修复这个问题。 |
nacos注册中心naming-server.log出现no instance我们已经初步定位到问题代码了,nacos-server的InstanceController收到list请求的serviceName名称里面没有providers:或consumers:前缀,但是nacos注册中心serviceMap里面的entrykey要么是有consumers:前缀,要么是有providers:前缀,所以找不到。 |
原因是nacos-sync忘了删掉一些配错了的同步任务,这些任务都漏了provider前缀,清掉这些任务之后nacos注册中心的naming-server日志暂时就没有再出现no instance了,还需要进一步排查。因为我们当时出现问题时,naming-sever日志开启了debug输出,里面并没有和客户端丢失服务相关的no instance日志内容。 |
你们也可以测试一下,写一个dubbo服务B,部署3~6台实例,一个dubbo客户端A,按下列步骤测试可以稳定复现问题:
|
如果是服务名错误,那就不是nacos的问题了,是注册和订阅的使用问题。 如果是sync配错了 ,那还是使用问题,如果是配对了,同步的时候丢了信息,那可能是sync的bug,需要再看看。 关于最后一个问题,需要分清是一直No provider还是出现一次然后再启动时又没有, 如果是,那应该只是获取地址列表可能有一定的延迟,启动时最好有一定的重试保护。 这个issue已经偏离了主题, 既然找到了主要问题是服务名配错导致服务找不到, 然后推空保护问题其实1.4.1已经支持,我认为issue可以关闭了。 |
最后一个问题是一直No provider,重启nacos注册服务中心才能恢复。(没有开启nacos sync) |
Describe the bug
dubbo服务上线、下线更新服务时,nacos-client的HostReactor处理服务列表更新的方法processServiceJson持续收到空hosts列表,导致客户端将服务列表清空,调用dubbo服务(版本2.7.5) 出现no provider,实际上dubbo服务一直运行正常。
测试环境:
nacos注册中心(集群多节点):1.4.1和1.2.1两个版本均测过
nacos客户端版本:1.4.1和1.2.1两个版本都会出现,使用1.4.1版本时问题更严重
1.4.1版本的com.alibaba.nacos.client.naming.core.HostReactor类的processServiceJson方法相比1.2.1,默认不再判断收到的serviceInfo内容是否合法(判断条件增加了一个配置选项pushEmptyProtection,默认为false)。
Expected behavior
Acutally behavior
收到的服务推送列表为empty时(serviceInfo.getHosts().size()==0)时,服务列表被动清空,导致调用dubbo服务出现No provider。
The text was updated successfully, but these errors were encountered: