Fix the issue: ArrayIndexOutOfBoundsException may be thrown when invokes taskDispatcher.addTask

This commit is contained in:
Andy 2019-03-29 22:18:53 +08:00
parent 95009390e5
commit 1f125c4af3
3 changed files with 76 additions and 9 deletions

View File

@ -17,10 +17,7 @@ package com.alibaba.nacos.naming.consistency.ephemeral.distro;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.naming.cluster.servers.Server;
import com.alibaba.nacos.naming.misc.GlobalConfig;
import com.alibaba.nacos.naming.misc.GlobalExecutor;
import com.alibaba.nacos.naming.misc.Loggers;
import com.alibaba.nacos.naming.misc.NetUtils;
import com.alibaba.nacos.naming.misc.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -58,12 +55,8 @@ public class TaskDispatcher {
}
}
public int mapTask(String key) {
return Math.abs(key.hashCode()) % partitionConfig.getTaskDispatchThreadCount();
}
public void addTask(String key) {
taskSchedulerList.get(mapTask(key)).addTask(key);
taskSchedulerList.get(UtilsAndCommons.shakeUp(key, partitionConfig.getTaskDispatchThreadCount())).addTask(key);
}
public class TaskScheduler implements Runnable {

View File

@ -237,4 +237,34 @@ public class UtilsAndCommons {
public static String assembleFullServiceName(String namespaceId, String serviceName) {
return namespaceId + UtilsAndCommons.NAMESPACE_SERVICE_CONNECTOR + serviceName;
}
/**
* 根据指定的字符串计算出一个0{@code upperLimit}不含之间的数字本方法会试图让不同的字符串较均匀的分布在0到{@code upperLimit}之间
* (Provide a number between 0(include) and {@code upperLimit}(exclude) for the given {@code string}, the number will be nearly uniform distribution.)
* <p>
* <p>
* 举个例子假设有N个提供相同服务的服务器地址被存在一个数组中为了实现负载均衡可以根据调用者的名字决定使用哪个服务器
* (e.g. Assume there's an array which contains some IP of the servers provide the same service, the caller name can be used to choose the server to achieve load balance.)
* <blockquote><pre>
* String[] serverIps = new String[10];
* int index = shakeUp("callerName", serverIps.length);
* String targetServerIp = serverIps[index];
* </pre></blockquote>
*
* @param string 字符串如果为null会固定返回0 (a string. the number 0 will be returned if it's null)
* @param upperLimit 返回值的上限必须为正整数(>0) (the upper limit of the returned number, must be a positive integer, which means > 0)
* @return 0到upperLimit不含之间的一个数字 (a number between 0(include) and upperLimit(exclude))
* @throws IllegalArgumentException if the upper limit equals or less than 0
* @since 1.0.0
*/
public static int shakeUp(String string, int upperLimit) {
if (upperLimit < 1) {
throw new IllegalArgumentException("upper limit must be greater than 0");
}
if (string == null) {
return 0;
}
return (string.hashCode() & Integer.MAX_VALUE) % upperLimit;
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed 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.alibaba.nacos.naming.consistency.ephemeral.distro;
import com.alibaba.nacos.naming.misc.GlobalConfig;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.util.ReflectionTestUtils;
/**
* @author jifengnan
*/
public class TaskDispatcherTest {
private TaskDispatcher taskDispatcher;
@Before
public void init() {
taskDispatcher = new TaskDispatcher();
GlobalConfig conf = new GlobalConfig();
ReflectionTestUtils.setField(conf, "taskDispatchThreadCount", 3);
ReflectionTestUtils.setField(taskDispatcher, "partitionConfig", conf);
taskDispatcher.init();
}
@Test
public void testAddTask() {
char[] chars = new char[]{2325, 9, 30, 12, 2};
taskDispatcher.addTask(new String(chars));
}
}