Skip to content

Commit

Permalink
[ISSUE#12644] Return cached instances when getAllInstance with subscr…
Browse files Browse the repository at this point in the history
…ibe exception (#12929)

* when get cached all instance with `subscribe` exception, will return cached instance not throw exception.

* For checkstyle
  • Loading branch information
KomachiSion authored Dec 6, 2024
1 parent 6029ea4 commit ee96df6
Show file tree
Hide file tree
Showing 4 changed files with 531 additions and 262 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.api.naming.selector.NamingContext;
import com.alibaba.nacos.api.naming.selector.NamingResult;
import com.alibaba.nacos.api.naming.selector.NamingSelector;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.api.selector.AbstractSelector;
Expand All @@ -37,6 +39,7 @@
import com.alibaba.nacos.client.naming.remote.NamingClientProxyDelegate;
import com.alibaba.nacos.client.naming.selector.NamingSelectorFactory;
import com.alibaba.nacos.client.naming.selector.NamingSelectorWrapper;
import com.alibaba.nacos.client.naming.selector.ServiceInfoContext;
import com.alibaba.nacos.client.naming.utils.CollectionUtils;
import com.alibaba.nacos.client.naming.utils.InitUtils;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
Expand Down Expand Up @@ -324,38 +327,67 @@ private List<Instance> selectInstances(ServiceInfo serviceInfo, boolean healthy)
return list;
}

private ServiceInfo getServiceInfoByFailover(String serviceName, String groupName, String clusterString) {
return serviceInfoHolder.getFailoverServiceInfo(serviceName, groupName, clusterString);
private ServiceInfo getServiceInfo(String serviceName, String groupName, List<String> clusters, boolean subscribe)
throws NacosException {
ServiceInfo serviceInfo;
NamingSelector clusterSelector = NamingSelectorFactory.newClusterSelector(clusters);
if (serviceInfoHolder.isFailoverSwitch()) {
serviceInfo = getServiceInfoByFailover(serviceName, groupName, clusterSelector);
if (serviceInfo != null && !serviceInfo.getHosts().isEmpty()) {
NAMING_LOGGER.debug("getServiceInfo from failover,serviceName: {} data:{}", serviceName,
JacksonUtils.toJson(serviceInfo.getHosts()));
return serviceInfo;
}
}
serviceInfo = getServiceInfoBySubscribe(serviceName, groupName, clusters, clusterSelector, subscribe);
return serviceInfo;
}

private ServiceInfo getServiceInfoBySubscribe(String serviceName, String groupName, String clusterString,
boolean subscribe) throws NacosException {
private ServiceInfo getServiceInfoByFailover(String serviceName, String groupName, NamingSelector clusterSelector) {
ServiceInfo result = serviceInfoHolder.getFailoverServiceInfo(serviceName, groupName, StringUtils.EMPTY);
return doSelectInstance(result, clusterSelector);
}

private ServiceInfo getServiceInfoBySubscribe(String serviceName, String groupName, List<String> clusters,
NamingSelector selector, boolean subscribe) throws NacosException {
ServiceInfo serviceInfo;
if (subscribe) {
serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, clusterString);
if (null == serviceInfo || !clientProxy.isSubscribed(serviceName, groupName, clusterString)) {
serviceInfo = clientProxy.subscribe(serviceName, groupName, clusterString);
}
serviceInfo = serviceInfoHolder.getServiceInfo(serviceName, groupName, StringUtils.EMPTY);
serviceInfo = tryToSubscribe(serviceName, groupName, serviceInfo);
serviceInfo = doSelectInstance(serviceInfo, selector);
} else {
String clusterString = NamingSelectorFactory.getUniqueClusterString(clusters);
serviceInfo = clientProxy.queryInstancesOfService(serviceName, groupName, clusterString, false);
}
return serviceInfo;
}

private ServiceInfo getServiceInfo(String serviceName, String groupName, List<String> clusters, boolean subscribe)
throws NacosException {
ServiceInfo serviceInfo;
String clusterString = StringUtils.join(clusters, ",");
if (serviceInfoHolder.isFailoverSwitch()) {
serviceInfo = getServiceInfoByFailover(serviceName, groupName, clusterString);
if (serviceInfo != null && serviceInfo.getHosts().size() > 0) {
NAMING_LOGGER.debug("getServiceInfo from failover,serviceName: {} data:{}", serviceName,
JacksonUtils.toJson(serviceInfo.getHosts()));
return serviceInfo;
}
private ServiceInfo tryToSubscribe(String serviceName, String groupName, ServiceInfo cachedServiceInfo) throws NacosException {
// not found in cache, service never subscribed.
if (null == cachedServiceInfo) {
return clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);
}

serviceInfo = getServiceInfoBySubscribe(serviceName, groupName, clusterString, subscribe);
// found in cache, and subscribed.
if (clientProxy.isSubscribed(serviceName, groupName, StringUtils.EMPTY)) {
return cachedServiceInfo;
}
// found in cached, but not subscribed, such as cached from local file when starting.
ServiceInfo result = cachedServiceInfo;
try {
result = clientProxy.subscribe(serviceName, groupName, StringUtils.EMPTY);
} catch (NacosException e) {
NAMING_LOGGER.warn("Subscribe from Server failed, will use local cache. fail message: ", e);
}
return result;
}

private ServiceInfo doSelectInstance(ServiceInfo serviceInfo, NamingSelector clusterSelector) {
if (null == serviceInfo) {
return null;
}
NamingContext context = new ServiceInfoContext(serviceInfo);
NamingResult result = clusterSelector.select(context);
serviceInfo.setHosts(result.getResult());
return serviceInfo;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 1999-2023 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.nacos.client.naming.selector;

import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.api.naming.pojo.ServiceInfo;
import com.alibaba.nacos.api.naming.selector.NamingContext;

import java.util.List;

/**
* Service info context.
*
* @author xiweng.yy
*/
public class ServiceInfoContext implements NamingContext {

private final ServiceInfo serviceInfo;

public ServiceInfoContext(ServiceInfo serviceInfo) {
this.serviceInfo = serviceInfo;
}

@Override
public String getServiceName() {
return serviceInfo.getName();
}

@Override
public String getGroupName() {
return serviceInfo.getGroupName();
}

@Override
public String getClusters() {
return serviceInfo.getClusters();
}

@Override
public List<Instance> getInstances() {
return serviceInfo.getHosts();
}
}
Loading

0 comments on commit ee96df6

Please sign in to comment.