apache / dubbo

The java implementation of Apache Dubbo. An RPC and microservice framework.
https://dubbo.apache.org/
Apache License 2.0
40.44k stars 26.42k forks source link

有时传给org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser的parseObject方法的raw config是个IP地址串 #8821

Closed zrlw closed 3 years ago

zrlw commented 3 years ago

Environment

通常传给parseObject的raw config入参是yml格式的字符串,如下面日志所示:

[16/09/21 02:16:21:021 UTC] ZookeeperDynamicConfiguration-thread-1  INFO integration.AbstractConfiguratorListener:  [DUBBO] Notification of overriding rule, change type is: MODIFIED, raw config content is:
 # Execute on governance-appoverride-provider.
# This will take effect on all services in governance-appoverride-provider.
---
configVersion: v2.7
scope: application
key: governance-appoverride-provider
enabled: true
configs:
- addresses: ["0.0.0.0:20880"]
  side: provider
  parameters:
    weight: 0
- addresses: ["0.0.0.0:20881"]
  side: provider
  parameters:
    weight: 100
..., dubbo version: 3.0.3-SNAPSHOT, current host: 172.21.0.3

但有时传入的内容却是个IP地址串,如下面日志所示的"172.21.0.5",此时就会因为类型不一致而抛异常: https://github.com/apache/dubbo/runs/3616815684?check_suite_focus=true

[16/09/21 02:16:21:021 UTC] ZookeeperDynamicConfiguration-thread-1  INFO integration.AbstractConfiguratorListener:  [DUBBO] Notification of overriding rule, change type is: MODIFIED, raw config content is:
 172.21.0.5, dubbo version: 3.0.3-SNAPSHOT, current host: 172.21.0.4
[16/09/21 02:16:21:021 UTC] ZookeeperDynamicConfiguration-thread-1 ERROR integration.AbstractConfiguratorListener:  [DUBBO] Failed to parse raw dynamic config and it will not take effect, the raw config is: 172.21.0.5, dubbo version: 3.0.3-SNAPSHOT, current host: 172.21.0.4
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map
    at org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser.parseObject(ConfigParser.java:76)
    at org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser.parseConfigurators(ConfigParser.java:51)
    at org.apache.dubbo.registry.integration.AbstractConfiguratorListener.genConfiguratorsFromRawRule(AbstractConfiguratorListener.java:107)
    at org.apache.dubbo.registry.integration.AbstractConfiguratorListener.process(AbstractConfiguratorListener.java:95)
    at org.apache.dubbo.configcenter.support.zookeeper.CacheListener.lambda$dataChanged$1(CacheListener.java:107)
    at java.util.concurrent.CopyOnWriteArrayList.forEach(CopyOnWriteArrayList.java:895)
    at java.util.concurrent.CopyOnWriteArraySet.forEach(CopyOnWriteArraySet.java:404)
    at org.apache.dubbo.configcenter.support.zookeeper.CacheListener.dataChanged(CacheListener.java:107)
    at org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient$NodeCacheListenerImpl.nodeChanged(CuratorZookeeperClient.java:345)
    at org.apache.curator.framework.recipes.cache.NodeCache$4.apply(NodeCache.java:326)
    at org.apache.curator.framework.recipes.cache.NodeCache$4.apply(NodeCache.java:320)
    at org.apache.curator.framework.listen.ListenerContainer$1.run(ListenerContainer.java:93)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
zrlw commented 3 years ago

debug跟踪了一下,如果是创建,zk通知的内容就是单个IP地址,只是ChildData的stat的version版本号是0,应该对version判断,非0才能视作data changed事件。 master分支的代码存在同样的问题。

haoyann commented 2 years ago

@zrlw Hi,我认为这不是好的解决方案,这样会有以下几个问题

  1. AbstractConfiguratorListener 本身就是监听的配置的变更,ADDED 事件不做任何处理,逻辑上不太通;
  2. 现在 zookeeper 变动配置只能使用 zkClient.setData().forPath(path, value.getBytes()); 的形式,zkClient.create() 则是 ADDED 事件,导致发布无效;
  3. 当 Nacos 作为配置中心的时候,新增配置无效,逻辑如下。
        private ConfigChangeType getChangeType(String configInfo, String oldValue) {
            if (StringUtils.isBlank(configInfo)) {
                return ConfigChangeType.DELETED;
            }
            if (StringUtils.isBlank(oldValue)) {
                return ConfigChangeType.ADDED;
            }
            return ConfigChangeType.MODIFIED;
        }

    回到这个问题本身,首先应该排查一下为什么会有 IP 字符串写入到这里,dubbo 监听的配置路径都是固定。即使有错误的字符串的输入,应该在解析那里中断流程,而不是在上游中断流程。

zrlw commented 2 years ago
  1. 调用org.apache.curator.framework.imps.CreateBuilderImpl.forPath创建path时才会触发服务端ADDED事件,此时CreateBuilderImpl.forPath传给服务端的data是CuratorFrameworkFactory的defaultData,值是localAddress(本机地址),所以事件内容为forPath调用者IP。
  2. AbstractConfiguratorListener目前dubbo只是处理Registry才使用(具体是org.apache.dubbo.registry.integration.RegistryProtocol、 org.apache.dubbo.registry.integration.RegistryDirectory、org.apache.dubbo.registry.client.ServiceDiscoveryRegistryDirectory三个类的内部listener类),功能是解析服务实例的URL,配置中心新增动态配置应该用不到这个类。