GitHub user mz0113 edited a discussion: [General][Java SDK (Component)]
serviceConfig.getRegistries() return null when destroy service , casuing
NullPointerExcetpion
### Pre-check
- [X] I am sure that all the content I provide is in English.
### Apache Dubbo Component
Java SDK (apache/dubbo)
### Details
` private void doExport(Instance interfaceInstance, List<String> registries,
BridgelessItem bridgelessItem)
throws ClassNotFoundException, ExecutionException,
InterruptedException, TimeoutException {
ClassLoader interfaceClassLoader = bridgelessItem.getClassLoader();
Map<String, String> interfaceInstanceMetadata =
interfaceInstance.getMetadata();
List<RegistryConfig> registryConfigs = getRegistryConfigs(registries);
if (registryConfigs.size() == 0) {
log.info("no matched zk,skip
export,bridgelessItem:{},interfaceInstance:{}", bridgelessItem,
interfaceInstance);
return;
}
//protocol
ProtocolConfig protocolConfig = getProtocolConfig();
//service
String anInterface = interfaceInstanceMetadata.get(Constants.INTERFACE);
ServiceConfig serviceConfig;
if (MobileAdapterService.class.getCanonicalName().equals(anInterface)) {
serviceConfig = new MGSAdapterServiceConfig();
} else {
serviceConfig = new ServiceConfig();
}
serviceConfig.setRegistries(registryConfigs);
serviceConfig.setProtocol(protocolConfig);
serviceConfig.setInterface(anInterface);
String version = interfaceInstanceMetadata.get(Constants.VERSION);
serviceConfig.setVersion(version);
// 设置权重,小于0的话说明未配置权重,使用全局默认权重
Integer weight = bridgelessItem.getBridgelessConfig().getWeight();
if (weight >= 0) {
serviceConfig.setWeight(weight);
}
//解决dubbo3.0.10的tri协议存在group被默认填充tri的问题
String group = interfaceInstanceMetadata.get(Constants.GROUP);
if (Constants.PROTOCOL_TRI.equals(group)) {
serviceConfig.setGroup("");
} else {
serviceConfig.setGroup(group);
}
String generic = interfaceInstanceMetadata.get(Constants.GENERIC);
if (StringUtils.isNotBlank(generic)) {
serviceConfig.setGeneric(generic);
}
serviceConfig.setInterfaceClassLoader(interfaceClassLoader);
serviceConfig.setRef(DubboReferenceHelper.getRef(interfaceInstance,
bridgelessItem, metaRPCHelper));
//tag会被dubbo.provider.tag覆盖,所以需要手动fresh()+setProviderConfig
String timeout = interfaceInstanceMetadata.get(Constants.TIMEOUT);
if (StringUtils.isNotBlank(timeout)) {
serviceConfig.setTimeout(Integer.parseInt(timeout));
}
serviceConfig.refresh();
// solveThreadPoolConfig(serviceConfig);
// 解决只新增方法无效问题
serviceConfig.setProxy("jdk");
serviceConfig.setTag("");
ProviderConfig providerConfig = getProviderConfig(timeout);
serviceConfig.setProvider(providerConfig);
// 注册服务
serviceConfig.export();
bridgelessItem.getServiceConfigList().add(serviceConfig);
log.info("export
success,appName:{},env:{},link:{},interface:{},version:{},group:{},serviceConfig:{}",
bridgelessItem.getBridgelessConfig().getAppName(),
bridgelessItem.getBridgelessConfig().getEnv(),
bridgelessItem.getBridgelessConfig().getLink(), anInterface,
version, group,
serviceConfig);
}
public void destroySync(BridgelessConfig bridgelessConfig, boolean
retainClassLoader)
throws IOException, InterruptedException {
DubboProtocol dubboProtocol =
DubboProtocol.getDubboProtocol(ApplicationModel.defaultModel());
BridgelessItem bridgelessItem =
bridgelessItemCache.getLocalCache(bridgelessConfig.getAppName(),
bridgelessConfig.getEnv(), bridgelessConfig.getLink());
List<ServiceConfig> serviceConfigList =
bridgelessItem.getServiceConfigList();
int toUnExportedSize = serviceConfigList.size();
int countDownSize = 0;
for (ServiceConfig serviceConfig : serviceConfigList) {
int size = serviceConfig.getRegistries().size();
countDownSize += size;
}
CountDownLatch countDownLatch = new CountDownLatch(countDownSize);
//registry -> registerProviderUrl
HashMap<Registry, URL> toRegistryMap = new HashMap<>();
for (ServiceConfig serviceConfig : serviceConfigList) {
try {
destroyRegistry(toRegistryMap, serviceConfig);
} catch (Exception e) {
LogUtil.error(log, "error when destroyRegistry:{}", () -> e);
}
}
//留出一点时间,用于受理C端残余的流量(zk异步通知有时延)
TimeUnit.MILLISECONDS.sleep(unRegistryAhead);
for (ServiceConfig serviceConfig : serviceConfigList) {
try {
serviceConfig.unexport();
} catch (Exception e) {
LogUtil.error(log, "exception when
unExport,serviceConfig:{},e:", () -> serviceConfig, () -> e);
//防止死锁
countDownLatch.countDown();
}
ModuleModel scopeModel = serviceConfig.getScopeModel();
String path = serviceConfig.getPath();
if (StringUtils.isBlank(path)) {
path = serviceConfig.getInterface();
}
String version = serviceConfig.getVersion();
String group = serviceConfig.getGroup();
String serviceKey = BaseServiceMetadata.buildServiceKey(path,
version, group);
//同步unexport走完后才放入,让异步unexport后去countDown
BridgelessItemCache.setCountDownLatch2Cache(scopeModel, serviceKey,
countDownLatch);
}
//countdown的替代方案
// TimeUnit.MILLISECONDS.sleep(unExportDelay);
LogUtil.debug(log, "before await");
countDownLatch.await(unExportDelay, TimeUnit.MILLISECONDS);
LogUtil.debug(log, "exporters:{}", () ->
dubboProtocol.getExporters().size());
if (retainClassLoader) {//保留classLoader,以便于下次复用
bridgelessItem.setBridgelessConfig(null);
bridgelessItem.getServiceConfigList().clear();
} else {
Set<Class> interfaceSet =
serviceConfigList.stream().map(serviceConfig ->
serviceConfig.getInterfaceClass())
.collect(Collectors.toSet());
bridgelessItemCache.deleteLocalCache(bridgelessConfig.getAppName(),
bridgelessConfig.getEnv(),
bridgelessConfig.getLink());
//dubbo中unExport时没有删除缓存,这里补删,否则由于dubbo缓存中不考虑classLoader隔离导致调用失败
pojoUtilsExpandUtil.deleteDubboPojoUtilCache(interfaceSet,
bridgelessItem.getClassLoader());
}
//如果原本需要unExport的服务个数大于0,则输出一下日志
if (toUnExportedSize > 0) {
log.info("unExport success,appName:{},env:{},link:{}",
bridgelessConfig.getAppName(),
bridgelessConfig.getEnv(), bridgeLink);
}
}`
### Code of Conduct
- [X] I agree to follow this project's [Code of
Conduct](https://www.apache.org/foundation/policies/conduct)
GitHub link: https://github.com/apache/dubbo/discussions/15502
----
This is an automatically sent email for [email protected].
To unsubscribe, please send an email to:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]