From 0439048d73d0264b64d41ad94ca0d16dd26f9433 Mon Sep 17 00:00:00 2001 From: "liujianjun.ljj" Date: Wed, 9 Nov 2022 21:55:32 +0800 Subject: [PATCH 1/6] fix triple multi classloader switch problem --- .../rpc/server/triple/GenericServiceImpl.java | 20 ++++----- .../sofa/rpc/server/triple/TripleServer.java | 44 ++++++++++++------- .../rpc/server/triple/UniqueIdInvoker.java | 26 ++++++++--- .../server/triple/GenericServiceImplTest.java | 11 ++++- 4 files changed, 67 insertions(+), 34 deletions(-) diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java index 00c06f150..9af4b9e76 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java @@ -23,6 +23,7 @@ import com.alipay.sofa.rpc.common.utils.ClassUtils; import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; +import com.alipay.sofa.rpc.context.RpcInvokeContext; import com.alipay.sofa.rpc.core.exception.RpcErrorType; import com.alipay.sofa.rpc.core.exception.SofaRpcException; import com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException; @@ -52,18 +53,11 @@ public class GenericServiceImpl extends SofaGenericServiceTriple.GenericServiceI private static final Logger LOGGER = LoggerFactory.getLogger(GenericServiceImpl.class); - protected Invoker invoker; - protected ProviderConfig providerConfig; + protected UniqueIdInvoker invoker; - public GenericServiceImpl(Invoker invoker, ProviderConfig providerConfig) { + public GenericServiceImpl(UniqueIdInvoker invoker) { super(); this.invoker = invoker; - this.providerConfig = providerConfig; - String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); - // 缓存接口的方法 - for (Method m : providerConfig.getProxyClass().getMethods()) { - ReflectCache.putOverloadMethodCache(key, m); - } } @Override @@ -74,8 +68,9 @@ public void generic(Request request, StreamObserver responseObserver) SofaRequest sofaRequest = TracingContextKey.getKeySofaRequest().get(Context.current()); String methodName = sofaRequest.getMethodName(); try { + ProviderConfig providerConfig = invoker.getProviderConfigByUniqueId(getUniqueIdFromInvokeContext()); String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); - ClassLoader interfaceClassLoader = providerConfig.getProxyClass().getClassLoader(); + ClassLoader interfaceClassLoader = ReflectCache.getServiceClassLoader(key); Thread.currentThread().setContextClassLoader(interfaceClassLoader); Class[] argTypes = getArgTypes(request); @@ -145,4 +140,9 @@ private Object[] getInvokeArgs(Request request, Class[] argTypes, Serializer ser } return args; } + + private String getUniqueIdFromInvokeContext() { + String uniqueId = (String) RpcInvokeContext.getContext().get(TripleContants.SOFA_UNIQUE_ID); + return uniqueId == null ? "" : uniqueId; + } } \ No newline at end of file diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/TripleServer.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/TripleServer.java index 6d3dcbf14..b5268a0f7 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/TripleServer.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/TripleServer.java @@ -242,9 +242,14 @@ public void stop() { @Override public void registerProcessor(ProviderConfig providerConfig, Invoker instance) { - Object ref = providerConfig.getRef(); this.lock.lock(); try { + String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); + ReflectCache.registerServiceClassLoader(key, providerConfig.getProxyClass().getClassLoader()); + // 缓存接口的方法 + for (Method m : providerConfig.getProxyClass().getMethods()) { + ReflectCache.putOverloadMethodCache(key, m); + } // wrap invoker to support unique id UniqueIdInvoker oldInvoker = this.invokerMap.putIfAbsent(providerConfig.getInterfaceId(), new UniqueIdInvoker()); if (null != oldInvoker) { @@ -261,22 +266,7 @@ public void registerProcessor(ProviderConfig providerConfig, Invoker instance) { throw new IllegalStateException("Can not expose service with interface:" + providerConfig.getInterfaceId() + " and unique id: " + providerConfig.getUniqueId()); } - // create service definition - ServerServiceDefinition serviceDef; - if (SofaProtoUtils.isProtoClass(ref)) { - // refer is BindableService - this.setBindableProxiedImpl(providerConfig, uniqueIdInvoker); - BindableService bindableService = (BindableService) providerConfig.getRef(); - serviceDef = bindableService.bindService(); - } else { - GenericServiceImpl genericService = new GenericServiceImpl(uniqueIdInvoker, providerConfig); - genericService.setProxiedImpl(genericService); - serviceDef = buildSofaServiceDef(genericService, providerConfig); - } - - List interceptorList = buildInterceptorChain(serviceDef); - ServerServiceDefinition serviceDefinition = ServerInterceptors.intercept( - serviceDef, interceptorList); + ServerServiceDefinition serviceDefinition = getServerServiceDefinition(providerConfig, uniqueIdInvoker); this.serviceInfo.put(providerConfig, serviceDefinition); ServerServiceDefinition ssd = this.handlerRegistry.addService(serviceDefinition); if (ssd != null) { @@ -294,6 +284,26 @@ public void registerProcessor(ProviderConfig providerConfig, Invoker instance) { } } + private ServerServiceDefinition getServerServiceDefinition(ProviderConfig providerConfig, UniqueIdInvoker uniqueIdInvoker) { + // create service definition + ServerServiceDefinition serviceDef; + if (SofaProtoUtils.isProtoClass(providerConfig.getRef())) { + // refer is BindableService + this.setBindableProxiedImpl(providerConfig, uniqueIdInvoker); + BindableService bindableService = (BindableService) providerConfig.getRef(); + serviceDef = bindableService.bindService(); + } else { + GenericServiceImpl genericService = new GenericServiceImpl(uniqueIdInvoker); + genericService.setProxiedImpl(genericService); + serviceDef = buildSofaServiceDef(genericService, providerConfig); + } + + List interceptorList = buildInterceptorChain(serviceDef); + ServerServiceDefinition serviceDefinition = ServerInterceptors.intercept( + serviceDef, interceptorList); + return serviceDefinition; + } + private void setBindableProxiedImpl(ProviderConfig providerConfig, Invoker invoker) { Class implClass = providerConfig.getRef().getClass(); try { diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java index 7f725e057..f95d689b7 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java @@ -39,19 +39,22 @@ */ public class UniqueIdInvoker implements Invoker { - private ReadWriteLock rwLock; + private ReadWriteLock rwLock; - private Lock readLock; + private Lock readLock; - private Lock writeLook; + private Lock writeLook; - private Map uniqueIdInvokerMap; + private Map uniqueIdInvokerMap; + + private Map uniqueIdProviderConfigMap; public UniqueIdInvoker() { this.rwLock = new ReentrantReadWriteLock(); this.readLock = this.rwLock.readLock(); this.writeLook = this.rwLock.writeLock(); this.uniqueIdInvokerMap = new HashMap<>(); + this.uniqueIdProviderConfigMap = new HashMap<>(); } /** @@ -65,7 +68,8 @@ public boolean registerInvoker(ProviderConfig providerConfig, Invoker invoker) { this.writeLook.lock(); try { String uniqueId = this.getUniqueId(providerConfig); - return this.uniqueIdInvokerMap.putIfAbsent(uniqueId, invoker) == null; + return this.uniqueIdInvokerMap.putIfAbsent(uniqueId, invoker) == null && + this.uniqueIdProviderConfigMap.putIfAbsent(uniqueId, providerConfig) == null; } finally { this.writeLook.unlock(); } @@ -81,7 +85,8 @@ public boolean unRegisterInvoker(ProviderConfig providerConfig) { this.writeLook.lock(); try { String uniqueId = this.getUniqueId(providerConfig); - return this.uniqueIdInvokerMap.remove(uniqueId) != null; + return this.uniqueIdInvokerMap.remove(uniqueId) != null && + this.uniqueIdProviderConfigMap.remove(uniqueId) != null; } finally { this.writeLook.unlock(); } @@ -99,6 +104,15 @@ public boolean hasInvoker() { } } + public ProviderConfig getProviderConfigByUniqueId(String uniqueId) { + this.readLock.lock(); + try { + return uniqueIdProviderConfigMap.get(uniqueId); + } finally { + this.readLock.unlock(); + } + } + /** * get unique id from provider config, this function won't return null * diff --git a/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java b/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java index b5b1b046c..914cec5ca 100644 --- a/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java +++ b/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java @@ -19,6 +19,7 @@ import com.alipay.sofa.rpc.codec.Serializer; import com.alipay.sofa.rpc.codec.SerializerFactory; import com.alipay.sofa.rpc.codec.sofahessian.SofaHessianSerializer; +import com.alipay.sofa.rpc.common.cache.ReflectCache; import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; import com.alipay.sofa.rpc.core.request.SofaRequest; @@ -53,8 +54,16 @@ public GenericServiceImplTest(){ providerConfig = new ProviderConfig<>(); providerConfig.setRef(new HelloServiceImpl()); providerConfig.setInterfaceId(HelloService.class.getName()); + String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); + ReflectCache.registerServiceClassLoader(key, providerConfig.getProxyClass().getClassLoader()); + // 缓存接口的方法 + for (Method m : providerConfig.getProxyClass().getMethods()) { + ReflectCache.putOverloadMethodCache(key, m); + } ProviderInvoker invoker = new ProviderInvoker<>(providerConfig); - genericService = new GenericServiceImpl(invoker,providerConfig); + UniqueIdInvoker uniqueIdInvoker = new UniqueIdInvoker(); + uniqueIdInvoker.registerInvoker(providerConfig, invoker); + genericService = new GenericServiceImpl(uniqueIdInvoker); responseObserver = new MockStreamObserver<>(); } From 5e9748497b10dec5ca44c63d636dfb85f5ea3bfd Mon Sep 17 00:00:00 2001 From: "liujianjun.ljj" Date: Thu, 1 Dec 2022 11:06:57 +0800 Subject: [PATCH 2/6] fix triple client and server log uniqueName without version info --- .../rpc/server/triple/GenericServiceImpl.java | 22 ++----- .../rpc/server/triple/UniqueIdInvoker.java | 66 +++++++++++++------ 2 files changed, 51 insertions(+), 37 deletions(-) diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java index 9af4b9e76..bc4ff19ca 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java @@ -18,18 +18,13 @@ import com.alipay.sofa.rpc.codec.Serializer; import com.alipay.sofa.rpc.codec.SerializerFactory; -import com.alipay.sofa.rpc.common.cache.ReflectCache; import com.alipay.sofa.rpc.common.utils.ClassTypeUtils; import com.alipay.sofa.rpc.common.utils.ClassUtils; -import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; -import com.alipay.sofa.rpc.config.ProviderConfig; -import com.alipay.sofa.rpc.context.RpcInvokeContext; import com.alipay.sofa.rpc.core.exception.RpcErrorType; import com.alipay.sofa.rpc.core.exception.SofaRpcException; import com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException; import com.alipay.sofa.rpc.core.request.SofaRequest; import com.alipay.sofa.rpc.core.response.SofaResponse; -import com.alipay.sofa.rpc.invoke.Invoker; import com.alipay.sofa.rpc.log.Logger; import com.alipay.sofa.rpc.log.LoggerFactory; import com.alipay.sofa.rpc.tracer.sofatracer.TracingContextKey; @@ -68,16 +63,14 @@ public void generic(Request request, StreamObserver responseObserver) SofaRequest sofaRequest = TracingContextKey.getKeySofaRequest().get(Context.current()); String methodName = sofaRequest.getMethodName(); try { - ProviderConfig providerConfig = invoker.getProviderConfigByUniqueId(getUniqueIdFromInvokeContext()); - String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); - ClassLoader interfaceClassLoader = ReflectCache.getServiceClassLoader(key); - Thread.currentThread().setContextClassLoader(interfaceClassLoader); + ClassLoader serviceClassLoader = invoker.getServiceClassLoader(); + if (serviceClassLoader != null) { + Thread.currentThread().setContextClassLoader(serviceClassLoader); + } + Method declaredMethod = invoker.getDeclaredMethod(sofaRequest, request); Class[] argTypes = getArgTypes(request); Serializer serializer = SerializerFactory.getSerializer(request.getSerializeType()); - - Method declaredMethod = ReflectCache.getOverloadMethodCache(key, methodName, request.getArgTypesList() - .toArray(new String[0])); Object[] invokeArgs = getInvokeArgs(request, argTypes, serializer); // fill sofaRequest @@ -140,9 +133,4 @@ private Object[] getInvokeArgs(Request request, Class[] argTypes, Serializer ser } return args; } - - private String getUniqueIdFromInvokeContext() { - String uniqueId = (String) RpcInvokeContext.getContext().get(TripleContants.SOFA_UNIQUE_ID); - return uniqueId == null ? "" : uniqueId; - } } \ No newline at end of file diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java index f95d689b7..d917c0e90 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java @@ -16,7 +16,9 @@ */ package com.alipay.sofa.rpc.server.triple; +import com.alipay.sofa.rpc.common.cache.ReflectCache; import com.alipay.sofa.rpc.common.utils.StringUtils; +import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; import com.alipay.sofa.rpc.context.RpcInvokeContext; import com.alipay.sofa.rpc.core.exception.RpcErrorType; @@ -24,7 +26,10 @@ import com.alipay.sofa.rpc.core.request.SofaRequest; import com.alipay.sofa.rpc.core.response.SofaResponse; import com.alipay.sofa.rpc.invoke.Invoker; +import com.alipay.sofa.rpc.server.ProviderProxyInvoker; +import triple.Request; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; @@ -39,22 +44,19 @@ */ public class UniqueIdInvoker implements Invoker { - private ReadWriteLock rwLock; + private ReadWriteLock rwLock; - private Lock readLock; + private Lock readLock; - private Lock writeLook; + private Lock writeLook; - private Map uniqueIdInvokerMap; - - private Map uniqueIdProviderConfigMap; + private Map uniqueIdInvokerMap; public UniqueIdInvoker() { this.rwLock = new ReentrantReadWriteLock(); this.readLock = this.rwLock.readLock(); this.writeLook = this.rwLock.writeLock(); this.uniqueIdInvokerMap = new HashMap<>(); - this.uniqueIdProviderConfigMap = new HashMap<>(); } /** @@ -68,8 +70,7 @@ public boolean registerInvoker(ProviderConfig providerConfig, Invoker invoker) { this.writeLook.lock(); try { String uniqueId = this.getUniqueId(providerConfig); - return this.uniqueIdInvokerMap.putIfAbsent(uniqueId, invoker) == null && - this.uniqueIdProviderConfigMap.putIfAbsent(uniqueId, providerConfig) == null; + return this.uniqueIdInvokerMap.putIfAbsent(uniqueId, invoker) == null; } finally { this.writeLook.unlock(); } @@ -85,8 +86,7 @@ public boolean unRegisterInvoker(ProviderConfig providerConfig) { this.writeLook.lock(); try { String uniqueId = this.getUniqueId(providerConfig); - return this.uniqueIdInvokerMap.remove(uniqueId) != null && - this.uniqueIdProviderConfigMap.remove(uniqueId) != null; + return this.uniqueIdInvokerMap.remove(uniqueId) != null; } finally { this.writeLook.unlock(); } @@ -104,15 +104,6 @@ public boolean hasInvoker() { } } - public ProviderConfig getProviderConfigByUniqueId(String uniqueId) { - this.readLock.lock(); - try { - return uniqueIdProviderConfigMap.get(uniqueId); - } finally { - this.readLock.unlock(); - } - } - /** * get unique id from provider config, this function won't return null * @@ -178,4 +169,39 @@ private Invoker findInvoker(String interfaceName, String uniqueId) { } } + public ClassLoader getServiceClassLoader() { + String uniqueName = this.getCurrentUniqueName(); + if (uniqueName == null) { + return null; + } + return ReflectCache.getServiceClassLoader(uniqueName); + } + + public Method getDeclaredMethod(SofaRequest sofaRequest, Request request) { + String uniqueName = this.getCurrentUniqueName(); + if (uniqueName == null) { + return null; + } + return ReflectCache.getOverloadMethodCache(uniqueName, sofaRequest.getMethodName(), request + .getArgTypesList() + .toArray(new String[0])); + } + + private String getCurrentUniqueName() { + this.readLock.lock(); + try { + Invoker invoker = uniqueIdInvokerMap.get(getUniqueIdFromInvokeContext()); + ProviderConfig providerConfig = null; + if (invoker instanceof ProviderProxyInvoker) { + providerConfig = ((ProviderProxyInvoker) invoker).getProviderConfig(); + } + if (providerConfig == null) { + return null; + } + return ConfigUniqueNameGenerator.getUniqueName(providerConfig); + } finally { + this.readLock.unlock(); + } + } + } From 2814f40b152e5f0b3a0801fe2b2e71001fc727d9 Mon Sep 17 00:00:00 2001 From: "liujianjun.ljj" Date: Sun, 25 Dec 2022 21:58:42 +0800 Subject: [PATCH 3/6] fix triple client and server log uniqueName without version info --- .../alipay/sofa/rpc/server/triple/GenericServiceImplTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java b/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java index 914cec5ca..e0c566ec3 100644 --- a/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java +++ b/remoting/remoting-triple/src/test/java/com/alipay/sofa/rpc/server/triple/GenericServiceImplTest.java @@ -23,8 +23,8 @@ import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; import com.alipay.sofa.rpc.core.request.SofaRequest; -import com.alipay.sofa.rpc.filter.ProviderInvoker; import com.alipay.sofa.rpc.message.MessageBuilder; +import com.alipay.sofa.rpc.server.ProviderProxyInvoker; import com.alipay.sofa.rpc.tracer.sofatracer.TracingContextKey; import com.alipay.sofa.rpc.transport.ByteArrayWrapperByteBuf; import com.alipay.sofa.rpc.transport.triple.TripleClientInvoker; @@ -60,7 +60,7 @@ public GenericServiceImplTest(){ for (Method m : providerConfig.getProxyClass().getMethods()) { ReflectCache.putOverloadMethodCache(key, m); } - ProviderInvoker invoker = new ProviderInvoker<>(providerConfig); + ProviderProxyInvoker invoker = new ProviderProxyInvoker(providerConfig); UniqueIdInvoker uniqueIdInvoker = new UniqueIdInvoker(); uniqueIdInvoker.registerInvoker(providerConfig, invoker); genericService = new GenericServiceImpl(uniqueIdInvoker); From 335cef606c71ef94c6d62d92849c3c1ac9ffb717 Mon Sep 17 00:00:00 2001 From: "liujianjun.ljj" Date: Mon, 26 Dec 2022 00:00:10 +0800 Subject: [PATCH 4/6] fix triple client and server log uniqueName without version info --- .../rpc/server/triple/GenericServiceImpl.java | 10 ++++++---- .../rpc/server/triple/UniqueIdInvoker.java | 18 ++++++------------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java index bc4ff19ca..dff254195 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/GenericServiceImpl.java @@ -63,12 +63,14 @@ public void generic(Request request, StreamObserver responseObserver) SofaRequest sofaRequest = TracingContextKey.getKeySofaRequest().get(Context.current()); String methodName = sofaRequest.getMethodName(); try { - ClassLoader serviceClassLoader = invoker.getServiceClassLoader(); - if (serviceClassLoader != null) { - Thread.currentThread().setContextClassLoader(serviceClassLoader); - } + ClassLoader serviceClassLoader = invoker.getServiceClassLoader(sofaRequest); + Thread.currentThread().setContextClassLoader(serviceClassLoader); Method declaredMethod = invoker.getDeclaredMethod(sofaRequest, request); + if (declaredMethod == null) { + throw new SofaRpcException(RpcErrorType.SERVER_NOT_FOUND_INVOKER, "Cannot find invoke method " + + methodName); + } Class[] argTypes = getArgTypes(request); Serializer serializer = SerializerFactory.getSerializer(request.getSerializeType()); Object[] invokeArgs = getInvokeArgs(request, argTypes, serializer); diff --git a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java index d917c0e90..15b615bd3 100644 --- a/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java +++ b/remoting/remoting-triple/src/main/java/com/alipay/sofa/rpc/server/triple/UniqueIdInvoker.java @@ -169,34 +169,28 @@ private Invoker findInvoker(String interfaceName, String uniqueId) { } } - public ClassLoader getServiceClassLoader() { - String uniqueName = this.getCurrentUniqueName(); - if (uniqueName == null) { - return null; - } + public ClassLoader getServiceClassLoader(SofaRequest sofaRequest) { + String uniqueName = this.getServiceUniqueName(sofaRequest); return ReflectCache.getServiceClassLoader(uniqueName); } public Method getDeclaredMethod(SofaRequest sofaRequest, Request request) { - String uniqueName = this.getCurrentUniqueName(); - if (uniqueName == null) { - return null; - } + String uniqueName = this.getServiceUniqueName(sofaRequest); return ReflectCache.getOverloadMethodCache(uniqueName, sofaRequest.getMethodName(), request .getArgTypesList() .toArray(new String[0])); } - private String getCurrentUniqueName() { + private String getServiceUniqueName(SofaRequest sofaRequest) { this.readLock.lock(); try { - Invoker invoker = uniqueIdInvokerMap.get(getUniqueIdFromInvokeContext()); + Invoker invoker = this.findInvoker(sofaRequest.getInterfaceName(), getUniqueIdFromInvokeContext()); ProviderConfig providerConfig = null; if (invoker instanceof ProviderProxyInvoker) { providerConfig = ((ProviderProxyInvoker) invoker).getProviderConfig(); } if (providerConfig == null) { - return null; + throw new SofaRpcException(RpcErrorType.SERVER_NOT_FOUND_INVOKER, "Cannot find providerConfig"); } return ConfigUniqueNameGenerator.getUniqueName(providerConfig); } finally { From 72b10382732d48f173bc781de795973741a8b63b Mon Sep 17 00:00:00 2001 From: "liujianjun.ljj" Date: Tue, 3 Jan 2023 01:19:22 +0800 Subject: [PATCH 5/6] add two uniqueId case --- .../TripleClientRegistryApplication.java | 2 +- .../sofa/rpc/test/triple/GreeterImpl2.java | 58 ++++++++++++++++ .../rpc/test/triple/TripleServerTest.java | 49 +++++++++++++ .../rpc/triple/TripleHessianInterface.java | 2 + .../triple/TripleHessianInterfaceImpl.java | 9 +++ .../rpc/triple/TripleHessianInvokeTest.java | 68 +++++++++++++++++++ 6 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/GreeterImpl2.java diff --git a/example/src/test/java/com/alipay/sofa/rpc/triple/TripleClientRegistryApplication.java b/example/src/test/java/com/alipay/sofa/rpc/triple/TripleClientRegistryApplication.java index 4c8e7dfd9..7a0ab355a 100644 --- a/example/src/test/java/com/alipay/sofa/rpc/triple/TripleClientRegistryApplication.java +++ b/example/src/test/java/com/alipay/sofa/rpc/triple/TripleClientRegistryApplication.java @@ -44,7 +44,7 @@ public static void main(String[] args) { .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) //.setRegistry(registryConfig) .setApplication(clientApp) - .setDirectUrl("tri://10.15.232.18:19544") + .setDirectUrl("tri://127.0.0.1:50051") .setRegister(false); SofaGreeterTriple.IGreeter greeterBlockingStub = consumerConfig.refer(); diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/GreeterImpl2.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/GreeterImpl2.java new file mode 100644 index 000000000..625788cf8 --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/GreeterImpl2.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test.triple; + +import io.grpc.examples.helloworld.HelloReply; +import io.grpc.examples.helloworld.HelloRequest; +import io.grpc.examples.helloworld.SofaGreeterTriple; +import io.grpc.stub.StreamObserver; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +/** + * @author Even + * @date 2023/1/3 12:17 AM + */ +public class GreeterImpl2 extends SofaGreeterTriple.GreeterImplBase { + + //Intentionally using unsupported format + static final DateTimeFormatter[] datetimeFormatter = new DateTimeFormatter[] { DateTimeFormatter.ISO_DATE_TIME, + DateTimeFormatter.ISO_LOCAL_DATE_TIME, + DateTimeFormatter.BASIC_ISO_DATE }; + + @Override + public void sayHello(HelloRequest req, StreamObserver responseObserver) { + HelloRequest.DateTime reqDateTime = req.getDateTime(); + int i = 0; + try { + i = Integer.parseInt(reqDateTime.getTime()); + } catch (Exception e) { + //TODO: handle exception + } + LocalDateTime dt = LocalDateTime.now(); + String dtStr = dt.format(datetimeFormatter[i % datetimeFormatter.length]); + HelloRequest.DateTime rplyDateTime = HelloRequest.DateTime.newBuilder(reqDateTime) + .setDate(dtStr).build(); + HelloReply reply = HelloReply.newBuilder() + .setMessage("Hello2 " + req.getName()) + .setDateTime(rplyDateTime) + .build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } +} \ No newline at end of file diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/TripleServerTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/TripleServerTest.java index 93bb26758..7014b1ce5 100644 --- a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/TripleServerTest.java +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/TripleServerTest.java @@ -242,6 +242,55 @@ public void testSyncTimeout() { Assert.assertTrue(exp); } + @Test + public void testExposeTwoUniqueId() { + ApplicationConfig applicationConfig = new ApplicationConfig().setAppName("triple-server1"); + + int port = 50052; + + ServerConfig serverConfig = new ServerConfig() + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setPort(port); + + ProviderConfig providerConfig = new ProviderConfig() + .setApplication(applicationConfig) + .setUniqueId("abc") + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(SofaGreeterTriple.IGreeter.class.getName()) + .setRef(new GreeterImpl()) + .setServer(serverConfig); + + providerConfig.export(); + + ProviderConfig providerConfig2 = new ProviderConfig() + .setApplication(applicationConfig) + .setUniqueId("abcd") + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(SofaGreeterTriple.IGreeter.class.getName()) + .setRef(new GreeterImpl2()) + .setServer(serverConfig); + providerConfig2.export(); + + ConsumerConfig consumerConfig = new ConsumerConfig<>(); + consumerConfig.setInterfaceId(SofaGreeterTriple.IGreeter.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setUniqueId("abc") + .setDirectUrl("tri://127.0.0.1:" + port); + SofaGreeterTriple.IGreeter greeterBlockingStub = consumerConfig.refer(); + HelloRequest.DateTime dateTime = HelloRequest.DateTime.newBuilder().setDate("2018-12-28").setTime("11:13:00") + .build(); + HelloRequest request = HelloRequest.newBuilder().setName("world").setDateTime(dateTime).build(); + Assert.assertEquals("Hello world", greeterBlockingStub.sayHello(request).getMessage()); + + ConsumerConfig consumerConfig2 = new ConsumerConfig<>(); + consumerConfig2.setInterfaceId(SofaGreeterTriple.IGreeter.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setUniqueId("abcd") + .setDirectUrl("tri://127.0.0.1:" + port); + SofaGreeterTriple.IGreeter greeterBlockingStub2 = consumerConfig2.refer(); + Assert.assertEquals("Hello2 world", greeterBlockingStub2.sayHello(request).getMessage()); + } + @BeforeClass public static void adBeforeClass() { RpcRunningState.setUnitTestMode(true); diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterface.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterface.java index cbe176baa..e526a3fad 100644 --- a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterface.java +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterface.java @@ -26,6 +26,8 @@ public interface TripleHessianInterface { String call1(); + String findFlag(); + Response call2(Request request); boolean testPressureMark(String name); diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterfaceImpl.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterfaceImpl.java index 768d6573b..f232b8dcb 100644 --- a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterfaceImpl.java +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInterfaceImpl.java @@ -33,6 +33,10 @@ public TripleHessianInterfaceImpl() { this.flag = ""; } + public TripleHessianInterfaceImpl(String flag) { + this.flag = flag; + } + @Override public void call() { this.flag = "call"; @@ -44,6 +48,11 @@ public String call1() { return flag; } + @Override + public String findFlag() { + return this.flag; + } + @Override public Response call2(Request request) { if (request != null) { diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInvokeTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInvokeTest.java index bdfddf3ca..ad88a35e3 100644 --- a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInvokeTest.java +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/TripleHessianInvokeTest.java @@ -269,6 +269,74 @@ public void testExposeTwice() { serverConfig.destroy(); } + @Test + public void testExposeTwoUniqueId() { + String uniqueId = "uniqueId"; + RpcRunningState.setDebugMode(true); + + ApplicationConfig clientApp = new ApplicationConfig().setAppName("triple-client"); + + ApplicationConfig serverApp = new ApplicationConfig().setAppName("triple-server"); + + int port = getPort(); + + ServerConfig serverConfig = new ServerConfig() + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setPort(port); + + TripleHessianInterfaceImpl ref = new TripleHessianInterfaceImpl("test1"); + ProviderConfig providerConfig = getProviderConfig() + .setApplication(serverApp) + .setUniqueId(uniqueId) + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(TripleHessianInterface.class.getName()) + .setRef(ref) + .setServer(serverConfig) + .setRegister(false); + + providerConfig.export(); + + String uniqueId2 = "uniqueId2"; + RpcRunningState.setDebugMode(true); + + TripleHessianInterfaceImpl ref2 = new TripleHessianInterfaceImpl("test2"); + ProviderConfig providerConfig2 = getProviderConfig() + .setApplication(serverApp) + .setUniqueId(uniqueId2) + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(TripleHessianInterface.class.getName()) + .setRef(ref2) + .setServer(serverConfig) + .setRegister(false); + providerConfig2.export(); + + ConsumerConfig consumerConfig = new ConsumerConfig<>(); + consumerConfig.setInterfaceId(TripleHessianInterface.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setDirectUrl("localhost:" + port) + .setUniqueId(uniqueId) + .setRegister(false) + .setApplication(clientApp); + TripleHessianInterface helloService = consumerConfig.refer(); + LOGGER.info("Grpc stub bean successful: {}", helloService.getClass().getName()); + Assert.assertEquals("test1", helloService.findFlag()); + + ConsumerConfig consumerConfig2 = new ConsumerConfig<>(); + consumerConfig2.setInterfaceId(TripleHessianInterface.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setDirectUrl("localhost:" + port) + .setUniqueId(uniqueId2) + .setRegister(false) + .setApplication(clientApp); + TripleHessianInterface helloService2 = consumerConfig2.refer(); + LOGGER.info("Grpc stub bean successful: {}", helloService2.getClass().getName()); + Assert.assertEquals("test2", helloService2.findFlag()); + + providerConfig2.unExport(); + providerConfig.unExport(); + serverConfig.destroy(); + } + @Test public void testTripleRpcInvokeContext() { ApplicationConfig clientApp = new ApplicationConfig().setAppName("triple-client"); From 36c8db87401815899d7b94b1622c1085770a0bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9D=87=E6=BA=90?= Date: Tue, 3 Jan 2023 14:50:36 +0800 Subject: [PATCH 6/6] feat: tri test case 4 ark --- .../rpc/test/AnotherHelloServiceImpl.java | 51 ++++ .../rpc/triple/ark/MultiClassLoaderTest.java | 278 ++++++++++++++++++ 2 files changed, 329 insertions(+) create mode 100644 test/test-common/src/main/java/com/alipay/sofa/rpc/test/AnotherHelloServiceImpl.java create mode 100644 test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/ark/MultiClassLoaderTest.java diff --git a/test/test-common/src/main/java/com/alipay/sofa/rpc/test/AnotherHelloServiceImpl.java b/test/test-common/src/main/java/com/alipay/sofa/rpc/test/AnotherHelloServiceImpl.java new file mode 100644 index 000000000..eddf1b66e --- /dev/null +++ b/test/test-common/src/main/java/com/alipay/sofa/rpc/test/AnotherHelloServiceImpl.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.test; + +/** + * + * @author GengZhang + */ +public class AnotherHelloServiceImpl implements HelloService { + + private int sleep; + + private String result; + + public AnotherHelloServiceImpl() { + + } + + public AnotherHelloServiceImpl(String result) { + this.result = result; + } + + public AnotherHelloServiceImpl(int sleep) { + this.sleep = sleep; + } + + @Override + public String sayHello(String name, int age) { + if (sleep > 0) { + try { + Thread.sleep(sleep); + } catch (Exception ignore) { + } + } + return result != null ? result : "hello " + name + " from server! age: " + age; + } +} diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/ark/MultiClassLoaderTest.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/ark/MultiClassLoaderTest.java new file mode 100644 index 000000000..0d173dc71 --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/triple/ark/MultiClassLoaderTest.java @@ -0,0 +1,278 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.alipay.sofa.rpc.triple.ark; + +import com.alipay.sofa.rpc.common.RpcConstants; +import com.alipay.sofa.rpc.config.ApplicationConfig; +import com.alipay.sofa.rpc.config.ConsumerConfig; +import com.alipay.sofa.rpc.config.ProviderConfig; +import com.alipay.sofa.rpc.config.ServerConfig; +import com.alipay.sofa.rpc.test.AnotherHelloServiceImpl; +import com.alipay.sofa.rpc.test.HelloService; +import com.alipay.sofa.rpc.test.HelloServiceImpl; +import org.junit.Test; +import org.springframework.util.Assert; + +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * + * @author junyuan + * @version MultiClassLoaderTest.java, v 0.1 2022年12月30日 15:02 junyuan Exp $ + */ +public class MultiClassLoaderTest { + + private static final AtomicInteger PORT = new AtomicInteger(51003); + + public void init() { + + } + + /* + * Launcher.AppClassLoader -> HelloService (Interface) + * / \ + * / \ + * cl1 cl2 + * | | + * v v + * HelloServiceImpl AnotherHelloServiceImpl + */ + @Test + public void test() throws InterruptedException { + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + + URL url4Impl = HelloServiceImpl.class.getProtectionDomain().getCodeSource().getLocation(); + URL url4AnotherImpl = AnotherHelloServiceImpl.class.getProtectionDomain().getCodeSource().getLocation(); + + SpecificTestClassLoader cl1 = new SpecificTestClassLoader("test_classloader_1", new URL[]{url4Impl}, oldClassLoader); + cl1.addWhiteListClass(HelloServiceImpl.class.getName()); + + SpecificTestClassLoader cl2 = new SpecificTestClassLoader("test_classloader_2", new URL[]{url4AnotherImpl}, oldClassLoader); + cl2.addWhiteListClass(AnotherHelloServiceImpl.class.getName()); + + SpecificTestClassLoader clientClassloader = new SpecificTestClassLoader("client_classLoader", new URL[]{}, oldClassLoader); + + int port = getPort(); + + ServerConfig serverConfig = new ServerConfig() + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setPort(port); + + ApplicationConfig clientApp = new ApplicationConfig().setAppName("triple-client"); + ApplicationConfig serverApp = new ApplicationConfig().setAppName("triple-server"); + + Thread.currentThread().setContextClassLoader(cl1); + ProviderConfig providerConfig1 = getProviderConfig(1) + .setServer(serverConfig) + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(HelloService.class.getName()) + .setRef(new HelloServiceImpl()) + .setApplication(serverApp) + .setRegister(false) + .setUniqueId("helloService"); + providerConfig1.export(); + + Thread.currentThread().setContextClassLoader(cl2); + ProviderConfig providerConfig2 = getProviderConfig(1) + .setServer(serverConfig) + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(HelloService.class.getName()) + .setRef(new AnotherHelloServiceImpl()) + .setApplication(serverApp) + .setRegister(false) + .setUniqueId("anotherHelloService"); + providerConfig2.export(); + + Thread.currentThread().setContextClassLoader(clientClassloader); + ConsumerConfig consumerConfig1 = new ConsumerConfig<>(); + consumerConfig1.setInterfaceId(HelloService.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setDirectUrl("tri://127.0.0.1:" + port) + .setRegister(false) + .setApplication(clientApp) + .setUniqueId("helloService"); + HelloService helloService1 = consumerConfig1.refer(); + + ConsumerConfig consumerConfig2 = new ConsumerConfig<>(); + consumerConfig2.setInterfaceId(HelloService.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setDirectUrl("tri://127.0.0.1:" + port) + .setRegister(false) + .setApplication(clientApp) + .setUniqueId("anotherHelloService"); + HelloService helloService2 = consumerConfig2.refer(); + + String result1 = helloService1.sayHello("impl1", 1); + + Assert.isTrue(result1.contains("impl1"), "helloService1 run fail, result is " + result1); + + String result2 = helloService2.sayHello("impl2", 2); + Assert.isTrue(result2.contains("impl2"), "anotherHelloService2 run fail, result is " + result2); + + Thread.currentThread().setContextClassLoader(cl1); + providerConfig1.unExport(); + Thread.currentThread().setContextClassLoader(cl2); + providerConfig2.unExport(); + + Thread.currentThread().setContextClassLoader(oldClassLoader); + serverConfig.destroy(); + + // ========================================================================================= + // then another brand new cl would do server init + SpecificTestClassLoader cl3 = new SpecificTestClassLoader("test_classloader_3", new URL[]{url4AnotherImpl}, oldClassLoader); + cl3.addWhiteListClass(AnotherHelloServiceImpl.class.getName()); + SpecificTestClassLoader clientClassloader2 = new SpecificTestClassLoader("client_classLoader_2", new URL[]{}, oldClassLoader); + + Thread.currentThread().setContextClassLoader(cl3); + ProviderConfig providerConfig3 = getProviderConfig(1) + .setServer(serverConfig) + .setBootstrap(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setInterfaceId(HelloService.class.getName()) + .setRef(new AnotherHelloServiceImpl()) + .setApplication(serverApp) + .setRegister(false) + .setUniqueId("anotherHelloService"); + providerConfig2.export(); + + Thread.currentThread().setContextClassLoader(clientClassloader2); + ConsumerConfig consumerConfig3 = new ConsumerConfig<>(); + consumerConfig3.setInterfaceId(HelloService.class.getName()) + .setProtocol(RpcConstants.PROTOCOL_TYPE_TRIPLE) + .setDirectUrl("tri://127.0.0.1:" + port) + .setRegister(false) + .setApplication(clientApp) + .setUniqueId("anotherHelloService"); + HelloService helloService3 = consumerConfig3.refer(); + + String result3 = helloService3.sayHello("impl3", 2); + Assert.isTrue(result3.contains("impl3"), "anotherHelloService3 run fail, result is " + result3); + + Thread.currentThread().setContextClassLoader(cl3); + providerConfig3.unExport(); + + Thread.currentThread().setContextClassLoader(oldClassLoader); + serverConfig.destroy(); + } + + + private ProviderConfig getProviderConfig(int exportLimit) { + ProviderConfig providerConfig = new ProviderConfig<>(); + providerConfig.setRepeatedExportLimit(exportLimit); + return providerConfig; + } + + + private int getPort() { + int andIncrement = PORT.getAndIncrement(); + return andIncrement; + } + + + + /** + * a specific classloader + * would load class with refClassloader if load nothing by itself + * logic of this classloader would be similar to com.alipay.sofa.ark.container.service.classloader.BizClassLoader + */ + class SpecificTestClassLoader extends URLClassLoader { + + private String identity; + + private ClassLoader refClassLoader; + + private Set blackList = new HashSet<>(); + + /** active only if not null */ + private Set whiteList = new HashSet<>(); + + public SpecificTestClassLoader(String identity, URL[] urls) { + super(urls); + this.identity = identity; + } + + public SpecificTestClassLoader(String identity, URL[] urls, ClassLoader ref) { + super(urls); + this.identity = identity; + this.refClassLoader = ref; + } + + @Override + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + Class clazz = null; + + // skip load if in black list + if (!blackList.contains(name)) { + clazz = whiteListLoad(name, resolve); + } + + if (clazz == null) { + clazz = refClassLoader.loadClass(name); + } + + if (clazz == null) { + throw new ClassNotFoundException(); + } + + return clazz; + } + + @Override + public Enumeration getResources(String name) throws IOException { + Enumeration urls = super.getResources(name); + if (!urls.hasMoreElements()) { + urls = refClassLoader.getResources(name); + } + return urls; + } + + @Override + public URL getResource(String name) { + URL url = super.getResource(name); + if (url == null ) { + url = refClassLoader.getResource(name); + } + return url; + } + + /** do load only if white list is not empty and class do in white list */ + private Class whiteListLoad(String className, boolean resolve) throws ClassNotFoundException { + Class clazz = null; + if (!whiteList.isEmpty()) { + if (!whiteList.contains(className)) { + // class is not allowed to load with current cl + return null; + } + } + + return super.loadClass(className, resolve); + } + + public void addBlackListClass(String className) { + this.blackList.add(className); + } + + public void addWhiteListClass(String className) { + this.whiteList.add(className); + } + } +} \ No newline at end of file