diff --git a/core/common/src/main/java/com/alipay/sofa/rpc/common/cache/ReflectCache.java b/core/common/src/main/java/com/alipay/sofa/rpc/common/cache/ReflectCache.java index 062c2c223..f9a02c8f5 100644 --- a/core/common/src/main/java/com/alipay/sofa/rpc/common/cache/ReflectCache.java +++ b/core/common/src/main/java/com/alipay/sofa/rpc/common/cache/ReflectCache.java @@ -195,7 +195,7 @@ public static void putMethodCache(String serviceName, Method method) { cache = old; } } - cache.putIfAbsent(method.getName(), method); + cache.put(method.getName(), method); } /** @@ -236,7 +236,7 @@ public static void putMethodSigsCache(String serviceName, String methodName, Str cacheSigs = old; } } - cacheSigs.putIfAbsent(methodName, argSigs); + cacheSigs.put(methodName, argSigs); } /** @@ -289,7 +289,7 @@ public static void putOverloadMethodCache(String serviceName, Method method) { for (Class paramType : method.getParameterTypes()) { mSigs.append(paramType.getName()); } - cache.putIfAbsent(mSigs.toString(), method); + cache.put(mSigs.toString(), method); } /** diff --git a/core/common/src/test/java/com/alipay/sofa/rpc/common/cache/ReflectCacheTest.java b/core/common/src/test/java/com/alipay/sofa/rpc/common/cache/ReflectCacheTest.java new file mode 100644 index 000000000..624b06a3a --- /dev/null +++ b/core/common/src/test/java/com/alipay/sofa/rpc/common/cache/ReflectCacheTest.java @@ -0,0 +1,67 @@ +/* + * 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.common.cache; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Method; + +/** + * @author zhangchengxi + */ +public class ReflectCacheTest { + + @After + public void teardown() { + ReflectCache.clearAll(); + } + + @Test + public void putOverloadMethodCache() throws NoSuchMethodException { + Method hashCode1 = String.class.getMethod("hashCode"); + Method hashCode2 = Object.class.getMethod("hashCode"); + ReflectCache.putOverloadMethodCache("service", hashCode1); + Assert.assertSame(hashCode1, ReflectCache.getOverloadMethodCache("service", "hashCode", new String[] {})); + + ReflectCache.putOverloadMethodCache("service", hashCode2); + Assert.assertSame(hashCode2, ReflectCache.getOverloadMethodCache("service", "hashCode", new String[] {})); + } + + @Test + public void putMethodCache() throws NoSuchMethodException { + Method hashCode1 = String.class.getMethod("hashCode"); + Method hashCode2 = Object.class.getMethod("hashCode"); + ReflectCache.putMethodCache("service", hashCode1); + Assert.assertSame(hashCode1, ReflectCache.getMethodCache("service", "hashCode")); + + ReflectCache.putMethodCache("service", hashCode2); + Assert.assertSame(hashCode2, ReflectCache.getMethodCache("service", "hashCode")); + } + + @Test + public void putMethodSigsCache() throws NoSuchMethodException { + String[] sign1 = { "a" }; + String[] sign2 = { "b" }; + ReflectCache.putMethodSigsCache("service", "hashCode", sign1); + Assert.assertSame(sign1, ReflectCache.getMethodSigsCache("service", "hashCode")); + + ReflectCache.putMethodSigsCache("service", "hashCode", sign2); + Assert.assertSame(sign2, ReflectCache.getMethodSigsCache("service", "hashCode")); + } +} \ No newline at end of file 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 30a283b64..00c06f150 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 @@ -21,6 +21,7 @@ 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.core.exception.RpcErrorType; import com.alipay.sofa.rpc.core.exception.SofaRpcException; @@ -30,7 +31,6 @@ 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.message.MessageBuilder; import com.alipay.sofa.rpc.tracer.sofatracer.TracingContextKey; import com.alipay.sofa.rpc.transport.ByteArrayWrapperByteBuf; import com.google.protobuf.ByteString; @@ -53,31 +53,36 @@ public class GenericServiceImpl extends SofaGenericServiceTriple.GenericServiceI private static final Logger LOGGER = LoggerFactory.getLogger(GenericServiceImpl.class); protected Invoker invoker; - protected Class proxyClass; + protected ProviderConfig providerConfig; - public GenericServiceImpl(Invoker invoker, Class proxyClass) { + public GenericServiceImpl(Invoker invoker, ProviderConfig providerConfig) { super(); this.invoker = invoker; - this.proxyClass = proxyClass; // todo use reflect to get Class + this.providerConfig = providerConfig; + String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); + // 缓存接口的方法 + for (Method m : providerConfig.getProxyClass().getMethods()) { + ReflectCache.putOverloadMethodCache(key, m); + } } @Override public void generic(Request request, StreamObserver responseObserver) { - SofaRequest sofaRequest = TracingContextKey.getKeySofaRequest().get(Context.current()); + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + SofaRequest sofaRequest = TracingContextKey.getKeySofaRequest().get(Context.current()); String methodName = sofaRequest.getMethodName(); - String interfaceName = sofaRequest.getInterfaceName(); - ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); try { - Class proxyClass = ClassTypeUtils.getClass(interfaceName); - ClassLoader interfaceClassLoader = proxyClass.getClassLoader(); + String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); + ClassLoader interfaceClassLoader = providerConfig.getProxyClass().getClassLoader(); Thread.currentThread().setContextClassLoader(interfaceClassLoader); Class[] argTypes = getArgTypes(request); Serializer serializer = SerializerFactory.getSerializer(request.getSerializeType()); - Method declaredMethod = proxyClass.getDeclaredMethod(methodName, argTypes); + Method declaredMethod = ReflectCache.getOverloadMethodCache(key, methodName, request.getArgTypesList() + .toArray(new String[0])); Object[] invokeArgs = getInvokeArgs(request, argTypes, serializer); // fill sofaRequest 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 6046912f4..6d3dcbf14 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 @@ -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.struct.NamedThreadFactory; +import com.alipay.sofa.rpc.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; import com.alipay.sofa.rpc.config.ServerConfig; import com.alipay.sofa.rpc.core.exception.SofaRpcRuntimeException; @@ -267,7 +269,7 @@ public void registerProcessor(ProviderConfig providerConfig, Invoker instance) { BindableService bindableService = (BindableService) providerConfig.getRef(); serviceDef = bindableService.bindService(); } else { - GenericServiceImpl genericService = new GenericServiceImpl(uniqueIdInvoker, providerConfig.getProxyClass()); + GenericServiceImpl genericService = new GenericServiceImpl(uniqueIdInvoker, providerConfig); genericService.setProxiedImpl(genericService); serviceDef = buildSofaServiceDef(genericService, providerConfig); } @@ -380,6 +382,7 @@ protected List buildInterceptorChain(ServerServiceDefin @Override public void unRegisterProcessor(ProviderConfig providerConfig, boolean closeIfNoEntry) { this.lock.lock(); + cleanReflectCache(providerConfig); try { ServerServiceDefinition serverServiceDefinition = this.serviceInfo.get(providerConfig); UniqueIdInvoker uniqueIdInvoker = this.invokerMap.get(providerConfig.getInterfaceId()); @@ -403,6 +406,14 @@ public void unRegisterProcessor(ProviderConfig providerConfig, boolean closeIfNo } } + public void cleanReflectCache(ProviderConfig providerConfig) { + String key = ConfigUniqueNameGenerator.getUniqueName(providerConfig); + ReflectCache.unRegisterServiceClassLoader(key); + ReflectCache.invalidateMethodCache(key); + ReflectCache.invalidateMethodSigsCache(key); + ReflectCache.invalidateOverloadMethodCache(key); + } + @Override public void destroy() { stop(); 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 dda7674aa..b5b1b046c 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.config.ConfigUniqueNameGenerator; import com.alipay.sofa.rpc.config.ProviderConfig; import com.alipay.sofa.rpc.core.request.SofaRequest; import com.alipay.sofa.rpc.filter.ProviderInvoker; @@ -46,18 +47,22 @@ public class GenericServiceImplTest { private GenericServiceImpl genericService; private MockStreamObserver responseObserver; + private ProviderConfig providerConfig; + public GenericServiceImplTest(){ - ProviderConfig providerConfig = new ProviderConfig<>(); + providerConfig = new ProviderConfig<>(); providerConfig.setRef(new HelloServiceImpl()); - providerConfig.setProxyClass(HelloService.class); + providerConfig.setInterfaceId(HelloService.class.getName()); ProviderInvoker invoker = new ProviderInvoker<>(providerConfig); - genericService = new GenericServiceImpl(invoker,providerConfig.getProxyClass()); + genericService = new GenericServiceImpl(invoker,providerConfig); responseObserver = new MockStreamObserver<>(); } @Test public void testPrimitiveType() throws NoSuchMethodException { // test return primitive type + Assert.assertEquals("com.alipay.sofa.rpc.server.triple.HelloService:1.0", + ConfigUniqueNameGenerator.getUniqueName(providerConfig)); String methodName = "testPrimitiveType"; Method method = HelloService.class.getDeclaredMethod(methodName, long.class); diff --git a/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/SampleService.java b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/SampleService.java new file mode 100644 index 000000000..69982a471 --- /dev/null +++ b/test/test-integration/src/test/java/com/alipay/sofa/rpc/test/triple/SampleService.java @@ -0,0 +1,27 @@ +/* + * 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; + +/** + * @author zhaowang + * @version : SampleService.java, v 0.1 2022年06月17日 3:33 PM zhaowang + */ +public interface SampleService { + + String hello(String name); + +} 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 6870dae2b..93bb26758 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,12 +242,6 @@ public void testSyncTimeout() { Assert.assertTrue(exp); } - public interface SampleService { - - String hello(String name); - - } - @BeforeClass public static void adBeforeClass() { RpcRunningState.setUnitTestMode(true);