CalvinKirs
4 years ago
10 changed files with 410 additions and 0 deletions
@ -0,0 +1,10 @@
|
||||
package org.apache.dolphinscheduler.remote.rpc; |
||||
|
||||
/** |
||||
* @author jiangli |
||||
* @date 2021-01-11 21:05 |
||||
*/ |
||||
public interface IUserService { |
||||
|
||||
String say(); |
||||
} |
@ -0,0 +1,21 @@
|
||||
package org.apache.dolphinscheduler.remote.rpc; |
||||
|
||||
import org.apache.dolphinscheduler.remote.rpc.client.IRpcClient; |
||||
import org.apache.dolphinscheduler.remote.rpc.client.RpcClient; |
||||
|
||||
/** |
||||
* @author jiangli |
||||
* @date 2021-01-11 21:06 |
||||
*/ |
||||
public class MainTest { |
||||
|
||||
public static void main(String[] args) throws Exception { |
||||
|
||||
RpcClient rpcClient = new RpcClient(); |
||||
IUserService userService = rpcClient.create(IUserService.class); |
||||
for (int i = 0; i < 100; i++) { |
||||
userService.say(); |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,12 @@
|
||||
package org.apache.dolphinscheduler.remote.rpc; |
||||
|
||||
/** |
||||
* @author jiangli |
||||
* @date 2021-01-11 21:05 |
||||
*/ |
||||
public class UserService implements IUserService{ |
||||
@Override |
||||
public String say() { |
||||
return null; |
||||
} |
||||
} |
@ -0,0 +1,59 @@
|
||||
package org.apache.dolphinscheduler.remote.rpc.filter.directory; |
||||
|
||||
import org.apache.dolphinscheduler.remote.rpc.filter.SelectorFilter; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
import org.slf4j.Logger; |
||||
import org.slf4j.LoggerFactory; |
||||
|
||||
/** |
||||
* Directory |
||||
*/ |
||||
public class Directory { |
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Directory.class); |
||||
|
||||
|
||||
private SelectorFilter selectorFilter = SelectorFilter.getInstance(); |
||||
|
||||
public static Directory getInstance() { |
||||
return Directory.DirectoryInner.INSTANCE; |
||||
} |
||||
|
||||
private static class DirectoryInner { |
||||
|
||||
private static final Directory INSTANCE = new Directory(); |
||||
} |
||||
|
||||
private Directory() { |
||||
} |
||||
|
||||
|
||||
private ConcurrentHashMap<String, List<String>> directoryMap = new ConcurrentHashMap<>(); |
||||
|
||||
public List<String> getDirectory(String serviceName) { |
||||
return directoryMap.get(serviceName); |
||||
} |
||||
|
||||
public boolean addServer(String serviceName, String servicePath) { |
||||
synchronized (this) { |
||||
if (directoryMap.containsKey(serviceName)) { |
||||
directoryMap.get(serviceName).add(servicePath); |
||||
return true; |
||||
} |
||||
} |
||||
directoryMap.putIfAbsent(serviceName, new ArrayList<>(Collections.singletonList(servicePath))); |
||||
return true; |
||||
} |
||||
|
||||
public boolean removeServer(String serviceName, String servicePath) { |
||||
|
||||
return true; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,87 @@
|
||||
/* |
||||
* 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.dolphinscheduler.remote.rpc.filter.selector; |
||||
|
||||
import org.apache.dolphinscheduler.remote.utils.Constants; |
||||
import org.apache.dolphinscheduler.remote.utils.Host; |
||||
|
||||
/** |
||||
* host weight |
||||
*/ |
||||
public class HostWeight { |
||||
|
||||
private final int CPU_FACTOR = 10; |
||||
|
||||
private final int MEMORY_FACTOR = 20; |
||||
|
||||
private final int LOAD_AVERAGE_FACTOR = 70; |
||||
|
||||
private final Host host; |
||||
|
||||
private final double weight; |
||||
|
||||
private double currentWeight; |
||||
|
||||
public HostWeight(Host host, double cpu, double memory, double loadAverage) { |
||||
this.weight = getWeight(cpu, memory, loadAverage, host); |
||||
this.host = host; |
||||
this.currentWeight = weight; |
||||
} |
||||
|
||||
public double getCurrentWeight() { |
||||
return currentWeight; |
||||
} |
||||
|
||||
public double getWeight() { |
||||
return weight; |
||||
} |
||||
|
||||
public void setCurrentWeight(double currentWeight) { |
||||
this.currentWeight = currentWeight; |
||||
} |
||||
|
||||
public Host getHost() { |
||||
return host; |
||||
} |
||||
|
||||
@Override |
||||
public String toString() { |
||||
return "HostWeight{" |
||||
+ "host=" + host |
||||
+ ", weight=" + weight |
||||
+ ", currentWeight=" + currentWeight |
||||
+ '}'; |
||||
} |
||||
|
||||
private double getWeight(double cpu, double memory, double loadAverage, Host host) { |
||||
double calculateWeight = cpu * CPU_FACTOR + memory * MEMORY_FACTOR + loadAverage * LOAD_AVERAGE_FACTOR; |
||||
return getWarmUpWeight(host, calculateWeight); |
||||
} |
||||
|
||||
/** |
||||
* If the warm-up is not over, add the weight |
||||
*/ |
||||
private double getWarmUpWeight(Host host, double weight) { |
||||
long startTime = host.getStartTime(); |
||||
long uptime = System.currentTimeMillis() - startTime; |
||||
if (uptime > 0 && uptime < Constants.WARM_UP_TIME) { |
||||
return weight * Constants.WARM_UP_TIME / uptime; |
||||
} |
||||
return weight; |
||||
} |
||||
} |
@ -0,0 +1,56 @@
|
||||
/* |
||||
* 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.dolphinscheduler.remote.rpc.filter.selector; |
||||
|
||||
|
||||
import org.apache.dolphinscheduler.remote.rpc.selector.AbstractSelector; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
/** |
||||
* lower weight round robin |
||||
*/ |
||||
public class LowerWeightRoundRobin extends AbstractSelector<HostWeight> { |
||||
|
||||
/** |
||||
* select |
||||
* |
||||
* @param sources sources |
||||
* @return HostWeight |
||||
*/ |
||||
@Override |
||||
public HostWeight doSelect(Collection<HostWeight> sources) { |
||||
double totalWeight = 0; |
||||
double lowWeight = 0; |
||||
HostWeight lowerNode = null; |
||||
for (HostWeight hostWeight : sources) { |
||||
totalWeight += hostWeight.getWeight(); |
||||
hostWeight.setCurrentWeight(hostWeight.getCurrentWeight() + hostWeight.getWeight()); |
||||
if (lowerNode == null || lowWeight > hostWeight.getCurrentWeight()) { |
||||
lowerNode = hostWeight; |
||||
lowWeight = hostWeight.getCurrentWeight(); |
||||
} |
||||
} |
||||
lowerNode.setCurrentWeight(lowerNode.getCurrentWeight() + totalWeight); |
||||
return lowerNode; |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,141 @@
|
||||
/* |
||||
* 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.dolphinscheduler.remote.rpc.filter.selector; |
||||
|
||||
import org.apache.dolphinscheduler.remote.rpc.selector.AbstractSelector; |
||||
import org.apache.dolphinscheduler.remote.utils.Host; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
import java.util.concurrent.ConcurrentMap; |
||||
import java.util.concurrent.atomic.AtomicBoolean; |
||||
import java.util.concurrent.atomic.AtomicLong; |
||||
|
||||
|
||||
/** |
||||
* Smooth Weight Round Robin |
||||
*/ |
||||
public class RoundRobinSelector extends AbstractSelector<Host> { |
||||
|
||||
private ConcurrentMap<String, ConcurrentMap<String, WeightedRoundRobin>> workGroupWeightMap = new ConcurrentHashMap<>(); |
||||
|
||||
private static final int RECYCLE_PERIOD = 100000; |
||||
|
||||
private AtomicBoolean updateLock = new AtomicBoolean(); |
||||
|
||||
protected static class WeightedRoundRobin { |
||||
private int weight; |
||||
private AtomicLong current = new AtomicLong(0); |
||||
private long lastUpdate; |
||||
|
||||
int getWeight() { |
||||
return weight; |
||||
} |
||||
|
||||
void setWeight(int weight) { |
||||
this.weight = weight; |
||||
current.set(0); |
||||
} |
||||
|
||||
long increaseCurrent() { |
||||
return current.addAndGet(weight); |
||||
} |
||||
|
||||
void sel(int total) { |
||||
current.addAndGet(-1L * total); |
||||
} |
||||
|
||||
long getLastUpdate() { |
||||
return lastUpdate; |
||||
} |
||||
|
||||
void setLastUpdate(long lastUpdate) { |
||||
this.lastUpdate = lastUpdate; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
@Override |
||||
public Host doSelect(Collection<Host> source) { |
||||
|
||||
List<Host> hosts = new ArrayList<>(source); |
||||
String key = hosts.get(0).getWorkGroup(); |
||||
ConcurrentMap<String, WeightedRoundRobin> map = workGroupWeightMap.get(key); |
||||
if (map == null) { |
||||
workGroupWeightMap.putIfAbsent(key, new ConcurrentHashMap<>()); |
||||
map = workGroupWeightMap.get(key); |
||||
} |
||||
|
||||
int totalWeight = 0; |
||||
long maxCurrent = Long.MIN_VALUE; |
||||
long now = System.currentTimeMillis(); |
||||
Host selectedHost = null; |
||||
WeightedRoundRobin selectWeightRoundRobin = null; |
||||
|
||||
for (Host host : hosts) { |
||||
String workGroupHost = host.getWorkGroup() + host.getAddress(); |
||||
WeightedRoundRobin weightedRoundRobin = map.get(workGroupHost); |
||||
int weight = host.getWeight(); |
||||
if (weight < 0) { |
||||
weight = 0; |
||||
} |
||||
|
||||
if (weightedRoundRobin == null) { |
||||
weightedRoundRobin = new WeightedRoundRobin(); |
||||
// set weight
|
||||
weightedRoundRobin.setWeight(weight); |
||||
map.putIfAbsent(workGroupHost, weightedRoundRobin); |
||||
weightedRoundRobin = map.get(workGroupHost); |
||||
} |
||||
if (weight != weightedRoundRobin.getWeight()) { |
||||
weightedRoundRobin.setWeight(weight); |
||||
} |
||||
|
||||
long cur = weightedRoundRobin.increaseCurrent(); |
||||
weightedRoundRobin.setLastUpdate(now); |
||||
if (cur > maxCurrent) { |
||||
maxCurrent = cur; |
||||
selectedHost = host; |
||||
selectWeightRoundRobin = weightedRoundRobin; |
||||
} |
||||
|
||||
totalWeight += weight; |
||||
} |
||||
|
||||
|
||||
if (!updateLock.get() && hosts.size() != map.size() && updateLock.compareAndSet(false, true)) { |
||||
try { |
||||
ConcurrentMap<String, WeightedRoundRobin> newMap = new ConcurrentHashMap<>(map); |
||||
newMap.entrySet().removeIf(item -> now - item.getValue().getLastUpdate() > RECYCLE_PERIOD); |
||||
workGroupWeightMap.put(key, newMap); |
||||
} finally { |
||||
updateLock.set(false); |
||||
} |
||||
} |
||||
|
||||
if (selectedHost != null) { |
||||
selectWeightRoundRobin.sel(totalWeight); |
||||
return selectedHost; |
||||
} |
||||
|
||||
return hosts.get(0); |
||||
} |
||||
} |
Loading…
Reference in new issue