You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2020/02/01 07:59:06 UTC

[dubbo] branch master updated: perf: Reduce object allocation for ContextFilter.invoke(Invoker, Invocation) and NetUtils.isInvalidLocalHost(String) (#5542)

This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new c355a1a  perf: Reduce object allocation for ContextFilter.invoke(Invoker, Invocation) and NetUtils.isInvalidLocalHost(String) (#5542)
c355a1a is described below

commit c355a1a836fd831d6f1f31f2c0763d6f0647e26e
Author: LinShunKang <li...@gmail.com>
AuthorDate: Sat Feb 1 15:58:59 2020 +0800

    perf: Reduce object allocation for ContextFilter.invoke(Invoker, Invocation) and NetUtils.isInvalidLocalHost(String) (#5542)
---
 .../org/apache/dubbo/common/utils/NetUtils.java    |   5 +-
 .../apache/dubbo/common/utils/NetUtilsTest.java    |   8 +-
 .../org/apache/dubbo/rpc/filter/ContextFilter.java | 258 +++++++++++----------
 3 files changed, 146 insertions(+), 125 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
index ee2aa61..6dfab2e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java
@@ -46,9 +46,10 @@ import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
  * IP and Port Helper for RPC
  */
 public class NetUtils {
+
     private static Logger logger;
 
-    {
+    static {
         logger = LoggerFactory.getLogger(NetUtils.class);
         if (logger instanceof FailsafeLogger) {
             logger = ((FailsafeLogger) logger).getLogger();
@@ -123,7 +124,7 @@ public class NetUtils {
                 || host.length() == 0
                 || host.equalsIgnoreCase(LOCALHOST_KEY)
                 || host.equals(ANYHOST_VALUE)
-                || (LOCAL_IP_PATTERN.matcher(host).matches());
+                || host.startsWith("127.");
     }
 
     public static boolean isValidLocalHost(String host) {
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
index f690ef7..9e0abde 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
@@ -39,6 +39,7 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class NetUtilsTest {
+
     @Test
     public void testGetRandomPort() throws Exception {
         assertThat(NetUtils.getRandomPort(), greaterThanOrEqualTo(30000));
@@ -87,11 +88,14 @@ public class NetUtilsTest {
         assertTrue(NetUtils.isInvalidLocalHost("localhost"));
         assertTrue(NetUtils.isInvalidLocalHost("0.0.0.0"));
         assertTrue(NetUtils.isInvalidLocalHost("127.1.2.3"));
+        assertTrue(NetUtils.isInvalidLocalHost("127.0.0.1"));
+        assertFalse(NetUtils.isInvalidLocalHost("128.0.0.1"));
     }
 
     @Test
     public void testIsValidLocalHost() throws Exception {
         assertTrue(NetUtils.isValidLocalHost("1.2.3.4"));
+        assertTrue(NetUtils.isValidLocalHost("128.0.0.1"));
     }
 
     @Test
@@ -243,7 +247,7 @@ public class NetUtilsTest {
         assertTrue(thrown.getMessage().contains("If you config ip expression that contains '*'"));
 
         thrown = assertThrows(IllegalArgumentException.class, () ->
-                        NetUtils.matchIpRange("234e:0:4567:3d", "234e:0:4567::3d:ff", 90));
+                NetUtils.matchIpRange("234e:0:4567:3d", "234e:0:4567::3d:ff", 90));
         assertTrue(thrown.getMessage().contains("The host is ipv6, but the pattern is not ipv6 pattern"));
 
         thrown =
@@ -282,7 +286,7 @@ public class NetUtilsTest {
     @Test
     public void testMatchIpv4WithIpPort() throws UnknownHostException {
         NumberFormatException thrown =
-                assertThrows(NumberFormatException.class, () ->NetUtils.matchIpExpression("192.168.1.192/26:90", "192.168.1.199", 90));
+                assertThrows(NumberFormatException.class, () -> NetUtils.matchIpExpression("192.168.1.192/26:90", "192.168.1.199", 90));
         assertTrue(thrown instanceof NumberFormatException);
 
         assertTrue(NetUtils.matchIpRange("*.*.*.*:90", "192.168.1.63", 90));
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
index e771f72..09520cd 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
@@ -1,121 +1,137 @@
-/*
- * 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 org.apache.dubbo.rpc.filter;
-
-import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.rpc.Filter;
-import org.apache.dubbo.rpc.Invocation;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Result;
-import org.apache.dubbo.rpc.RpcContext;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.RpcInvocation;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
-import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
-import static org.apache.dubbo.rpc.Constants.FORCE_USE_TAG;
-import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
-
-
-/**
- * ContextFilter set the provider RpcContext with invoker, invocation, local port it is using and host for
- * current execution thread.
- *
- * @see RpcContext
- */
-@Activate(group = PROVIDER, order = -10000)
-public class ContextFilter implements Filter, Filter.Listener2 {
-    private static final String TAG_KEY = "dubbo.tag";
-
-    @Override
-    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
-        Map<String, Object> attachments = invocation.getAttachments();
-        if (attachments != null) {
-            attachments = new HashMap<>(attachments);
-            attachments.remove(PATH_KEY);
-            attachments.remove(INTERFACE_KEY);
-            attachments.remove(GROUP_KEY);
-            attachments.remove(VERSION_KEY);
-            attachments.remove(DUBBO_VERSION_KEY);
-            attachments.remove(TOKEN_KEY);
-            attachments.remove(TIMEOUT_KEY);
-            // Remove async property to avoid being passed to the following invoke chain.
-            attachments.remove(ASYNC_KEY);
-            attachments.remove(TAG_KEY);
-            attachments.remove(FORCE_USE_TAG);
-        }
-        RpcContext context = RpcContext.getContext();
-
-        context.setInvoker(invoker)
-                .setInvocation(invocation)
-//                .setAttachments(attachments)  // merged from dubbox
-                .setLocalAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
-        String remoteApplication = (String) invocation.getAttachment(REMOTE_APPLICATION_KEY);
-        if (StringUtils.isNotEmpty(remoteApplication)) {
-            context.setRemoteApplicationName(remoteApplication);
-        } else {
-            context.setRemoteApplicationName((String) RpcContext.getContext().getAttachment(REMOTE_APPLICATION_KEY));
-
-        }
-
-
-        // merged from dubbox
-        // we may already added some attachments into RpcContext before this filter (e.g. in rest protocol)
-        if (attachments != null) {
-            if (RpcContext.getContext().getAttachments() != null) {
-                RpcContext.getContext().getAttachments().putAll(attachments);
-            } else {
-                RpcContext.getContext().setAttachments(attachments);
-            }
-        }
-
-        if (invocation instanceof RpcInvocation) {
-            ((RpcInvocation) invocation).setInvoker(invoker);
-        }
-        try {
-            RpcContext.getContext().clearAfterEachInvoke(false);
-            return invoker.invoke(invocation);
-        } finally {
-            RpcContext.getContext().clearAfterEachInvoke(true);
-            // IMPORTANT! For async scenario, we must remove context from current thread, so we always create a new RpcContext for the next invoke for the same thread.
-            RpcContext.removeContext();
-            RpcContext.removeServerContext();
-        }
-    }
-
-    @Override
-    public void onMessage(Result appResponse, Invoker<?> invoker, Invocation invocation) {
-        // pass attachments to result
-        appResponse.addAttachments(RpcContext.getServerContext().getAttachments());
-    }
-
-    @Override
-    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
-
-    }
-}
+/*
+ * 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 org.apache.dubbo.rpc.filter;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.RpcInvocation;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
+import static org.apache.dubbo.rpc.Constants.FORCE_USE_TAG;
+import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
+
+
+/**
+ * ContextFilter set the provider RpcContext with invoker, invocation, local port it is using and host for
+ * current execution thread.
+ *
+ * @see RpcContext
+ */
+@Activate(group = PROVIDER, order = -10000)
+public class ContextFilter implements Filter, Filter.Listener2 {
+
+    private static final String TAG_KEY = "dubbo.tag";
+
+    private static final Set<String> UNLOADING_KEYS;
+
+    static {
+        UNLOADING_KEYS = new HashSet<>(128);
+        UNLOADING_KEYS.add(PATH_KEY);
+        UNLOADING_KEYS.add(INTERFACE_KEY);
+        UNLOADING_KEYS.add(GROUP_KEY);
+        UNLOADING_KEYS.add(VERSION_KEY);
+        UNLOADING_KEYS.add(DUBBO_VERSION_KEY);
+        UNLOADING_KEYS.add(TOKEN_KEY);
+        UNLOADING_KEYS.add(TIMEOUT_KEY);
+
+        // Remove async property to avoid being passed to the following invoke chain.
+        UNLOADING_KEYS.add(ASYNC_KEY);
+        UNLOADING_KEYS.add(TAG_KEY);
+        UNLOADING_KEYS.add(FORCE_USE_TAG);
+    }
+
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        Map<String, Object> attachments = invocation.getAttachments();
+        if (attachments != null) {
+            Map<String, Object> newAttach = new HashMap<>(attachments.size());
+            for (Map.Entry<String, Object> entry : attachments.entrySet()) {
+                String key = entry.getKey();
+                if (!UNLOADING_KEYS.contains(key)) {
+                    newAttach.put(key, entry.getValue());
+                }
+            }
+            attachments = newAttach;
+        }
+
+        RpcContext context = RpcContext.getContext();
+        context.setInvoker(invoker)
+                .setInvocation(invocation)
+//                .setAttachments(attachments)  // merged from dubbox
+                .setLocalAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
+        String remoteApplication = (String) invocation.getAttachment(REMOTE_APPLICATION_KEY);
+        if (StringUtils.isNotEmpty(remoteApplication)) {
+            context.setRemoteApplicationName(remoteApplication);
+        } else {
+            context.setRemoteApplicationName((String) context.getAttachment(REMOTE_APPLICATION_KEY));
+        }
+
+        // merged from dubbox
+        // we may already added some attachments into RpcContext before this filter (e.g. in rest protocol)
+        if (attachments != null) {
+            if (context.getAttachments() != null) {
+                context.getAttachments().putAll(attachments);
+            } else {
+                context.setAttachments(attachments);
+            }
+        }
+
+        if (invocation instanceof RpcInvocation) {
+            ((RpcInvocation) invocation).setInvoker(invoker);
+        }
+
+        try {
+            context.clearAfterEachInvoke(false);
+            return invoker.invoke(invocation);
+        } finally {
+            context.clearAfterEachInvoke(true);
+            // IMPORTANT! For async scenario, we must remove context from current thread, so we always create a new RpcContext for the next invoke for the same thread.
+            RpcContext.removeContext();
+            RpcContext.removeServerContext();
+        }
+    }
+
+    @Override
+    public void onMessage(Result appResponse, Invoker<?> invoker, Invocation invocation) {
+        // pass attachments to result
+        appResponse.addAttachments(RpcContext.getServerContext().getAttachments());
+    }
+
+    @Override
+    public void onError(Throwable t, Invoker<?> invoker, Invocation invocation) {
+
+    }
+}