You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@rocketmq.apache.org by hu...@apache.org on 2021/12/01 10:38:02 UTC

[rocketmq] 11/11: 优化Topic和Group检查的性能,改变算法消除正则表达式匹配

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

huangli pushed a commit to branch 4.9.2_dev_community
in repository https://gitbox.apache.org/repos/asf/rocketmq.git

commit e70d8e46e159c8dc98c92ca8cb1bf0b5d53af08e
Author: sunshuangcheng <sh...@163.com>
AuthorDate: Mon Nov 22 11:25:11 2021 +0800

    优化Topic和Group检查的性能,改变算法消除正则表达式匹配
---
 .../org/apache/rocketmq/client/Validators.java     | 52 ++++++----------------
 .../org/apache/rocketmq/client/ValidatorsTest.java |  2 +-
 .../rocketmq/common/topic/TopicValidator.java      | 45 ++++++++++++++-----
 3 files changed, 47 insertions(+), 52 deletions(-)

diff --git a/client/src/main/java/org/apache/rocketmq/client/Validators.java b/client/src/main/java/org/apache/rocketmq/client/Validators.java
index cf5f078..0db55cc 100644
--- a/client/src/main/java/org/apache/rocketmq/client/Validators.java
+++ b/client/src/main/java/org/apache/rocketmq/client/Validators.java
@@ -17,8 +17,8 @@
 
 package org.apache.rocketmq.client;
 
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import static org.apache.rocketmq.common.topic.TopicValidator.isTopicOrGroupIllegal;
+
 import org.apache.rocketmq.client.exception.MQClientException;
 import org.apache.rocketmq.client.producer.DefaultMQProducer;
 import org.apache.rocketmq.common.UtilAll;
@@ -31,24 +31,10 @@ import org.apache.rocketmq.common.topic.TopicValidator;
  * Common Validator
  */
 public class Validators {
-    public static final String VALID_PATTERN_STR = "^[%|a-zA-Z0-9_-]+$";
-    public static final Pattern PATTERN = Pattern.compile(VALID_PATTERN_STR);
     public static final int CHARACTER_MAX_LENGTH = 255;
     public static final int TOPIC_MAX_LENGTH = 127;
 
     /**
-     * @return The resulting {@code String}
-     */
-    public static String getGroupWithRegularExpression(String origin, String patternStr) {
-        Pattern pattern = Pattern.compile(patternStr);
-        Matcher matcher = pattern.matcher(origin);
-        while (matcher.find()) {
-            return matcher.group(0);
-        }
-        return null;
-    }
-
-    /**
      * Validate group
      */
     public static void checkGroup(String group) throws MQClientException {
@@ -60,27 +46,15 @@ public class Validators {
             throw new MQClientException("the specified group is longer than group max length 255.", null);
         }
 
-        if (!regularExpressionMatcher(group, PATTERN)) {
-            throw new MQClientException(String.format(
-                "the specified group[%s] contains illegal characters, allowing only %s", group,
-                VALID_PATTERN_STR), null);
-        }
-
-    }
 
-    /**
-     * @return <tt>true</tt> if, and only if, the entire origin sequence matches this matcher's pattern
-     */
-    public static boolean regularExpressionMatcher(String origin, Pattern pattern) {
-        if (pattern == null) {
-            return true;
+        if (isTopicOrGroupIllegal(group)) {
+            throw new MQClientException(String.format(
+                    "the specified group[%s] contains illegal characters, allowing only %s", group,
+                    "^[%|a-zA-Z0-9_-]+$"), null);
         }
-        Matcher matcher = pattern.matcher(origin);
-        return matcher.matches();
     }
 
-    public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer)
-        throws MQClientException {
+    public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer) throws MQClientException {
         if (null == msg) {
             throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, "the message is null");
         }
@@ -112,16 +86,16 @@ public class Validators {
             throw new MQClientException("The specified topic is blank", null);
         }
 
-        if (!regularExpressionMatcher(topic, PATTERN)) {
-            throw new MQClientException(String.format(
-                "The specified topic[%s] contains illegal characters, allowing only %s", topic,
-                VALID_PATTERN_STR), null);
-        }
-
         if (topic.length() > TOPIC_MAX_LENGTH) {
             throw new MQClientException(
                 String.format("The specified topic is longer than topic max length %d.", TOPIC_MAX_LENGTH), null);
         }
+
+        if (isTopicOrGroupIllegal(topic)) {
+            throw new MQClientException(String.format(
+                    "The specified topic[%s] contains illegal characters, allowing only %s", topic,
+                    "^[%|a-zA-Z0-9_-]+$"), null);
+        }
     }
 
     public static void isSystemTopic(String topic) throws MQClientException {
diff --git a/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java b/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
index 343fe4b..aa448dc 100644
--- a/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/ValidatorsTest.java
@@ -44,7 +44,7 @@ public class ValidatorsTest {
             Validators.checkTopic(illegalTopic);
             failBecauseExceptionWasNotThrown(MQClientException.class);
         } catch (MQClientException e) {
-            assertThat(e).hasMessageStartingWith(String.format("The specified topic[%s] contains illegal characters, allowing only %s", illegalTopic, Validators.VALID_PATTERN_STR));
+            assertThat(e).hasMessageStartingWith(String.format("The specified topic[%s] contains illegal characters, allowing only %s", illegalTopic, "^[%|a-zA-Z0-9_-]+$"));
         }
     }
 
diff --git a/common/src/main/java/org/apache/rocketmq/common/topic/TopicValidator.java b/common/src/main/java/org/apache/rocketmq/common/topic/TopicValidator.java
index 7b0a839..5e67dc5 100644
--- a/common/src/main/java/org/apache/rocketmq/common/topic/TopicValidator.java
+++ b/common/src/main/java/org/apache/rocketmq/common/topic/TopicValidator.java
@@ -22,8 +22,6 @@ import org.apache.rocketmq.remoting.protocol.RemotingCommand;
 
 import java.util.HashSet;
 import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 public class TopicValidator {
 
@@ -38,9 +36,7 @@ public class TopicValidator {
     public static final String RMQ_SYS_OFFSET_MOVED_EVENT = "OFFSET_MOVED_EVENT";
 
     public static final String SYSTEM_TOPIC_PREFIX = "rmq_sys_";
-
-    private static final String VALID_PATTERN_STR = "^[%|a-zA-Z0-9_-]+$";
-    private static final Pattern PATTERN = Pattern.compile(VALID_PATTERN_STR);
+    public static final boolean[] VALID_CHAR_BIT_MAP = new boolean[128];
     private static final int TOPIC_MAX_LENGTH = 127;
 
     private static final Set<String> SYSTEM_TOPIC_SET = new HashSet<String>();
@@ -62,14 +58,39 @@ public class TopicValidator {
         SYSTEM_TOPIC_SET.add(RMQ_SYS_OFFSET_MOVED_EVENT);
 
         NOT_ALLOWED_SEND_TOPIC_SET.add(RMQ_SYS_SCHEDULE_TOPIC);
+
+        // regex:^[%|a-zA-Z0-9_-]+$
+        // %
+        VALID_CHAR_BIT_MAP['%'] = true;
+        // -
+        VALID_CHAR_BIT_MAP['-'] = true;
+        // _
+        VALID_CHAR_BIT_MAP['_'] = true;
+        for (int i = 0; i < VALID_CHAR_BIT_MAP.length; i++) {
+            if (i >= '0' && i <= '9') {
+                // 0-9
+                VALID_CHAR_BIT_MAP[i] = true;
+            } else if (i >= 'A' && i <= 'Z') {
+                // A-Z
+                VALID_CHAR_BIT_MAP[i] = true;
+            } else if (i >= 'a' && i <= 'z') {
+                // a-z
+                VALID_CHAR_BIT_MAP[i] = true;
+            }
+        }
     }
 
-    private static boolean regularExpressionMatcher(String origin, Pattern pattern) {
-        if (pattern == null) {
-            return true;
+    public static boolean isTopicOrGroupIllegal(String str) {
+        int strLen = str.length();
+        int len = VALID_CHAR_BIT_MAP.length;
+        boolean[] bitMap = VALID_CHAR_BIT_MAP;
+        for (int i = 0; i < strLen; i++) {
+            char ch = str.charAt(i);
+            if (ch >= len || !bitMap[ch]) {
+                return true;
+            }
         }
-        Matcher matcher = pattern.matcher(origin);
-        return matcher.matches();
+        return false;
     }
 
     public static boolean validateTopic(String topic, RemotingCommand response) {
@@ -80,9 +101,9 @@ public class TopicValidator {
             return false;
         }
 
-        if (!regularExpressionMatcher(topic, PATTERN)) {
+        if (isTopicOrGroupIllegal(topic)) {
             response.setCode(ResponseCode.SYSTEM_ERROR);
-            response.setRemark("The specified topic contains illegal characters, allowing only " + VALID_PATTERN_STR);
+            response.setRemark("The specified topic contains illegal characters, allowing only ^[%|a-zA-Z0-9_-]+$");
             return false;
         }