huwenming-saw commented on issue #10393:
URL: https://github.com/apache/dubbo/issues/10393#issuecomment-1263358980

   > > @404008945 provider 和 consumer 都升级,2.7 的早期有个版本注册是有问题的
   > 
   > @AlbumenJ 问题找到了。 
生产和消费者都是升级了最新版的2.7.16,另外nacos-client为1.3.3时有问题,**测试nacos-client版本为2.0.4已经没有问题了**
 **问题记录** 生产者注册服务名称逻辑为 org.apache.dubbo.common.URL#getColonSeparatedKey
   > 
   > ```java
   >   public String getColonSeparatedKey() {
   >         StringBuilder serviceNameBuilder = new StringBuilder();
   >         serviceNameBuilder.append(this.getServiceInterface());
   >         append(serviceNameBuilder, VERSION_KEY, false);
   >         append(serviceNameBuilder, GROUP_KEY, false);
   >         return serviceNameBuilder.toString();
   >     }
   > ```
   > 
   > 当version为空时并不会省略掉间隔符冒号 于是注册的服务名称是 
io.seata.samples.tcc.dubbo.action.TccActionOne::tcc 
![image](https://user-images.githubusercontent.com/39762246/183087088-3b0e2edc-6e12-4679-bee7-eba29a3e6be5.png)
   > 
   > 然后我又看了消费者启动时初始化invoke时,生成的订阅服务名称逻辑 
org.apache.dubbo.registry.nacos.NacosRegistry#getServiceNames0
   > 
   > ```java
   >  private Set<String> getServiceNames0(URL url) {
   >         NacosServiceName serviceName = createServiceName(url);
   > 
   >         final Set<String> serviceNames;
   > 
   >         if (serviceName.isConcrete()) { // is the concrete service name
   >             serviceNames = new LinkedHashSet<>();
   >             serviceNames.add(serviceName.toString());
   >             // Add the legacy service name since 2.7.6
   >             String legacySubscribedServiceName = 
getLegacySubscribedServiceName(url);
   >             if 
(!serviceName.toString().equals(legacySubscribedServiceName)) {
   >                 //avoid duplicated service names
   >                 serviceNames.add(legacySubscribedServiceName);
   >             }
   >         } else {
   >             serviceNames = filterServiceNames(serviceName);
   >         }
   > 
   >         return serviceNames;
   >     }
   > ```
   > 
   > 
![image](https://user-images.githubusercontent.com/39762246/183089364-348ab9ab-d533-4aa6-bcf0-bb1dde424725.png)
 version为空,新版服务名version为空,不会省略间隔符冒号,根据注释,为了兼容2.7.3以前的版本,另外生成服务名 
version为空并且把冒号也省略掉了。最终结果就是新版比旧版多了一个冒号。 后面会继续分别订阅这两个服务名称,其中一个服务名在注册中心不存在,是空服务。 
org.apache.dubbo.registry.nacos.NacosRegistry#doSubscribe(org.apache.dubbo.common.URL,
 org.apache.dubbo.registry.NotifyListener, java.util.Set<java.lang.String>)
   > 
   > ```java
   >  private void doSubscribe(final URL url, final NotifyListener listener, 
final Set<String> serviceNames) {
   >         execute(namingService -> {
   >             if (isServiceNamesWithCompatibleMode(url)) {
   >                 List<Instance> allCorrespondingInstanceList = 
Lists.newArrayList();
   > 
   >                 /**
   >                  * Get all instances with serviceNames to avoid instance 
overwrite and but with empty instance mentioned
   >                  * in https://github.com/apache/dubbo/issues/5885 and 
https://github.com/apache/dubbo/issues/5899
   >                  *
   >                  * namingService.getAllInstances with {@link 
org.apache.dubbo.registry.support.AbstractRegistry#registryUrl}
   >                  * default {@link DEFAULT_GROUP}
   >                  *
   >                  * in https://github.com/apache/dubbo/issues/5978
   >                  */
   >                 for (String serviceName : serviceNames) {
   >                     List<Instance> instances = 
namingService.getAllInstances(serviceName,
   >                             getUrl().getParameter(GROUP_KEY, 
Constants.DEFAULT_GROUP));
   >                     
NacosInstanceManageUtil.initOrRefreshServiceInstanceList(serviceName, 
instances);
   >                     allCorrespondingInstanceList.addAll(instances);
   >                 }
   >                 notifySubscriber(url, listener, 
allCorrespondingInstanceList);
   >                 for (String serviceName : serviceNames) {
   >                     subscribeEventListener(serviceName, url, listener);
   >                 }
   >             } else {
   >                 List<Instance> instances = new LinkedList<>();
   >                 for (String serviceName : serviceNames) {
   >                     
instances.addAll(namingService.getAllInstances(serviceName
   >                             , getUrl().getParameter(GROUP_KEY, 
Constants.DEFAULT_GROUP)));
   >                     notifySubscriber(url, listener, instances);
   >                     subscribeEventListener(serviceName, url, listener);
   >                 }
   >             }
   > 
   >         });
   >     }
   > ```
   > 
   > 上面有段很好的注释 ,**Get all instances with serviceNames to avoid instance 
overwrite and but with empty instance mentioned**获取所有的serviceNames 
的实例,防止被空的实例覆盖。看起来好像没有问题。 但是下面的循环serviceNames订阅
   > 
   > ```java
   >  for (String serviceName : serviceNames) {
   >                     subscribeEventListener(serviceName, url, listener);
   >   }
   > ```
   > 
   > 但是注册中心为nacos时 这里来到了nacos客户端 版本为1.3.3时
   > 
   > ```java
   > public void addListener(ServiceInfo serviceInfo, String clusters, 
EventListener listener) {
   >         
   >         NAMING_LOGGER.info("[LISTENER] adding " + serviceInfo.getName() + 
" with " + clusters + " to listener map");
   >         List<EventListener> observers = Collections.synchronizedList(new 
ArrayList<EventListener>());
   >         observers.add(listener);
   >         
   >         observers = 
observerMap.putIfAbsent(ServiceInfo.getKey(serviceInfo.getName(), clusters), 
observers);
   >         if (observers != null) {
   >             observers.add(listener);
   >         }
   >         
   >         serviceChanged(serviceInfo);
   >     }
   >     
   > ```
   > 
   > 
会发现在第一次添加监听器时还是会触发serviceChange,进而触发notify,重新刷新invoker,由于实例为空的服务名也被订阅,那么这时候还是可能会发生被空的实例覆盖的情况。
   
   
问一下您,看您的描述,即使升级到“生产和消费者都是升级了最新版的2.7.16,另外nacos-client为1.3.3时有问题,测试nacos-client版本为2.0.4已经没有问题了”您说的这种情况中的dubbo-2.7.16,nacos-2.0.4,还是会订阅一个空服务,这个空服务对应的接口还是同一个URL,这个时候难道就不会出现No
 provider available?;换另一个角度来说最好的解决方法还是需要提供group version值是最完美的解决方法是吗?期待您的回复,这个No 
provider available困扰我很久了


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to