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

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


The following commit(s) were added to refs/heads/master by this push:
     new c195af026 add leastActive load balance (#4326)
c195af026 is described below

commit c195af026440e3fe35be1d4e05c6110241ab4341
Author: mahaitao <[email protected]>
AuthorDate: Tue Jan 17 11:34:44 2023 +0800

    add leastActive load balance (#4326)
    
    * add least active load balance
    
    * feat:add unittest
    
    * feat:add sql
    
    * feat:fix
    
    * feat:fix
    
    Co-authored-by: mahaitao617 <[email protected]>
---
 db/init/mysql/schema.sql                           |  1 +
 db/init/oracle/schema.sql                          |  4 ++
 .../src/main/resources/sql-script/h2/schema.sql    |  2 +-
 .../shenyu/common/enums/LoadBalanceEnum.java       |  7 ++-
 .../loadbalancer/spi/LeastActiveLoadBalance.java   | 63 ++++++++++++++++++++++
 .../spi/LeastActiveLoadBalanceTest.java            | 58 ++++++++++++++++++++
 6 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index 05447eab4..7dcac7df9 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -1700,6 +1700,7 @@ INSERT INTO `shenyu_dict` VALUES ('1529402613195784192', 
'algorithmName', 'ALGOR
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784193', 'loadBalance', 
'LOAD_BALANCE', 'roundRobin', 'roundRobin', 'roundRobin', 2, 1, '2022-05-25 
18:02:52', '2022-05-25 18:02:52');
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784194', 'loadBalance', 
'LOAD_BALANCE', 'random', 'random', 'random', 1, 1, '2022-05-25 18:02:52', 
'2022-05-25 18:02:52');
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784195', 'loadBalance', 
'LOAD_BALANCE', 'hash', 'hash', 'hash', 0, 1, '2022-05-25 18:02:52', 
'2022-05-25 18:02:52');
+INSERT INTO `shenyu_dict` VALUES ('1572621976689762307', 'loadBalance', 
'LOAD_BALANCE', 'leastActive', 'leastActive', 'leastActive', 0, 1, '2022-05-25 
18:02:52', '2022-05-25 18:02:52');
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784196', 'status', 
'DIVIDE_STATUS', 'close', 'false', 'close', 1, 1, '2022-05-25 18:02:52', 
'2022-05-25 18:02:52');
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784197', 'status', 
'DIVIDE_STATUS', 'open', 'true', 'open', 0, 1, '2022-05-25 18:02:52', 
'2022-05-25 18:02:52');
 INSERT INTO `shenyu_dict` VALUES ('1529402613195784198', 'multiRuleHandle', 
'MULTI_RULE_HANDLE', 'multiple rule', '1', 'multiple rule', 1, 1, '2022-05-25 
18:02:52', '2022-05-25 18:02:52');
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 6432effdf..f9649fc19 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -1080,6 +1080,10 @@ insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, 
dict_code, dict_name)) *
 VALUES ('1545812228228259842', 'engine', 'engine', 'MergeTree', 'MergeTree', 
'', 1, 1);
 
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) 
*/ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, 
ENABLED)
+values ('1545812228228259843', 'loadBalance', 'LOAD_BALANCE', 'leastActive', 
'leastActive', 'leastActive', 1, 1);
+
+
 /*plugin*/
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
role, sort, enabled) VALUES ('1','sign','Authentication',  20, '0');
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name, 
role, sort,config,enabled) VALUES ('2','waf', 'Authentication', 
50,'{"model":"black"}','0');
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql 
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index a59d1de6e..9db108ee7 100755
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -496,7 +496,7 @@ INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, 
`dict_name`, `dict_v
 INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`, 
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1572621976689762304', 
'maskStatus', 'MASK_STATUS_TRUE', 'mask', 'true', '', 0, 1);
 INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`, 
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1572621976689762305', 
'engine', 'engine', 'ReplacingMergeTree', 'ReplacingMergeTree', '', 0, 1);
 INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`, 
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1572621976689762306', 
'engine', 'engine', 'MergeTree', 'MergeTree', '', 1, 1);
-
+INSERT IGNORE INTO `shenyu_dict` (`id`, `type`,`dict_code`, `dict_name`, 
`dict_value`, `desc`, `sort`, `enabled`) VALUES ('1572621976689762307', 
'loadBalance', 'LOAD_BALANCE', 'leastActive', 'leastActive', 'leastActive', 0, 
1);
 
 /*plugin*/
 INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`) VALUES 
('1','sign','Authentication',  20, '0');
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/LoadBalanceEnum.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/LoadBalanceEnum.java
index 5ac45b790..82ce53059 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/LoadBalanceEnum.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/LoadBalanceEnum.java
@@ -35,7 +35,12 @@ public enum LoadBalanceEnum {
     /**
      * Round robin load balance enum.
      */
-    ROUND_ROBIN(3, "roundRobin", true);
+    ROUND_ROBIN(3, "roundRobin", true),
+
+    /**
+     * least activity load balance enum.
+     */
+    LEAST_ACTIVITY(4, "leastActive", true);
 
     private final int code;
 
diff --git 
a/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
 
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
new file mode 100644
index 000000000..6b77486c9
--- /dev/null
+++ 
b/shenyu-loadbalancer/src/main/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalance.java
@@ -0,0 +1,63 @@
+/*
+ * 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.shenyu.loadbalancer.spi;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.spi.Join;
+
+/**
+ * least active algorithm impl.
+ */
+@Join
+public class LeastActiveLoadBalance extends AbstractLoadBalancer {
+
+    private Map<String, Integer> countMap = new ConcurrentHashMap<>();
+
+    @Override
+    protected Upstream doSelect(final List<Upstream> upstreamList, final 
String ip) {
+        Map<String, Upstream> domainList = new ConcurrentHashMap<>();
+        upstreamList.stream().forEach(upstream -> {
+            domainList.put(upstream.buildDomain(), upstream);
+        });
+        countMap.keySet().forEach(key -> {
+            if (!domainList.keySet().contains(key)) {
+                countMap.remove(key);
+            }
+        });
+        for (Upstream upstream:upstreamList) {
+            if (countMap.get(upstream.buildDomain()) == null) {
+                countMap.put(upstream.buildDomain(), 1);
+                return upstream;
+            } else {
+                countMap.put(upstream.buildDomain(), 
countMap.get(upstream.buildDomain()) + 1);
+            }
+        }
+        AtomicReference<String> leastDomainUrl = new 
AtomicReference<>(upstreamList.get(0).buildDomain());
+        countMap.keySet().forEach(key -> {
+            if (countMap.get(key) < countMap.get(leastDomainUrl)) {
+                leastDomainUrl.set(key);
+            }
+        });
+        return domainList.get(leastDomainUrl);
+    }
+    
+}
diff --git 
a/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.java
new file mode 100644
index 000000000..ea1e657e5
--- /dev/null
+++ 
b/shenyu-loadbalancer/src/test/java/org/apache/shenyu/loadbalancer/spi/LeastActiveLoadBalanceTest.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 org.apache.shenyu.loadbalancer.spi;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.junit.Assert;
+import org.junit.jupiter.api.Test;
+
+/**
+ * The type least activity load balance test.
+ */
+public class LeastActiveLoadBalanceTest {
+    private List<Upstream> onlyOneList = new ArrayList<>();
+
+    /**
+     * build upstream list.
+     * @throws Exception exception
+     */
+    public void buildUpstreamList() throws Exception {
+        Upstream upstream1 = Upstream.builder()
+                .url("baidu.com")
+                .protocol("https")
+                .build();
+        Upstream upstream2 = Upstream.builder()
+                .url("pro.jd.com")
+                .protocol("https")
+                .build();
+        onlyOneList.add(upstream1);
+        onlyOneList.add(upstream2);
+    }
+
+    @Test
+    public void testResponseTimeBalancer() throws Exception {
+        buildUpstreamList();
+        final LeastActiveLoadBalance leastActiveLoadBalance = new 
LeastActiveLoadBalance();
+        Upstream upstream = leastActiveLoadBalance.doSelect(onlyOneList, 
"localhost");
+        Upstream upstream1 = leastActiveLoadBalance.doSelect(onlyOneList, 
"localhost");
+        Assert.assertTrue((upstream.getUrl().equals("baidu.com") && 
upstream1.getUrl().equals("pro.jd.com")) || 
upstream1.getUrl().equals("baidu.com") && 
upstream.getUrl().equals("pro.jd.com"));
+
+    }
+}

Reply via email to