use of org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData in project incubator-pulsar by apache.
the class ModularLoadManagerImpl method updateAllBrokerData.
// As the leader broker, update the broker data map in loadData by querying ZooKeeper for the broker data put there
// by each broker via updateLocalBrokerData.
private void updateAllBrokerData() {
final Set<String> activeBrokers = getAvailableBrokers();
final Map<String, BrokerData> brokerDataMap = loadData.getBrokerData();
for (String broker : activeBrokers) {
try {
String key = String.format("%s/%s", LoadManager.LOADBALANCE_BROKERS_ROOT, broker);
final LocalBrokerData localData = brokerDataCache.get(key).orElseThrow(KeeperException.NoNodeException::new);
if (brokerDataMap.containsKey(broker)) {
// Replace previous local broker data.
brokerDataMap.get(broker).setLocalData(localData);
} else {
// Initialize BrokerData object for previously unseen
// brokers.
brokerDataMap.put(broker, new BrokerData(localData));
}
} catch (NoNodeException ne) {
// it only happens if we update-brokerData before availableBrokerCache refreshed with latest data and
// broker's delete-znode watch-event hasn't updated availableBrokerCache
brokerDataMap.remove(broker);
log.warn("[{}] broker load-report znode not present", broker, ne);
} catch (Exception e) {
log.warn("Error reading broker data from cache for broker - [{}], [{}]", broker, e.getMessage());
}
}
// Remove obsolete brokers.
for (final String broker : brokerDataMap.keySet()) {
if (!activeBrokers.contains(broker)) {
brokerDataMap.remove(broker);
}
}
}
use of org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData in project incubator-pulsar by apache.
the class OverloadShedder method findBundlesForUnloading.
/**
* Attempt to shed one bundle off every broker which is overloaded.
*
* @param loadData
* The load data to used to make the unloading decision.
* @param conf
* The service configuration.
* @return A map from bundles to unload to the brokers on which they are loaded.
*/
public Map<String, String> findBundlesForUnloading(final LoadData loadData, final ServiceConfiguration conf) {
selectedBundlesCache.clear();
final double overloadThreshold = conf.getLoadBalancerBrokerOverloadedThresholdPercentage() / 100.0;
final Map<String, Long> recentlyUnloadedBundles = loadData.getRecentlyUnloadedBundles();
for (final Map.Entry<String, BrokerData> entry : loadData.getBrokerData().entrySet()) {
final String broker = entry.getKey();
final BrokerData brokerData = entry.getValue();
final LocalBrokerData localData = brokerData.getLocalData();
final double maxUsage = localData.getMaxResourceUsage();
if (maxUsage >= overloadThreshold) {
log.info("Attempting to shed load on {}, which has max resource usage {}%", broker, maxUsage);
double maxMessageRate = Double.NEGATIVE_INFINITY;
String mostTaxingBundle = null;
if (localData.getBundles().size() > 1) {
for (final String bundle : localData.getBundles()) {
final BundleData bundleData = loadData.getBundleData().get(bundle);
if (bundleData == null) {
continue;
}
// Consider short-term message rate to address system resource burden
final TimeAverageMessageData shortTermData = bundleData.getShortTermData();
final double messageRate = shortTermData.getMsgRateIn() + shortTermData.getMsgRateOut();
// The burden of checking the timestamp is for the load manager, not the strategy.
if (messageRate > maxMessageRate && !recentlyUnloadedBundles.containsKey(bundle)) {
maxMessageRate = messageRate;
mostTaxingBundle = bundle;
}
}
if (mostTaxingBundle != null) {
selectedBundlesCache.put(broker, mostTaxingBundle);
} else {
log.warn("Load shedding could not be performed on broker {} because all bundles assigned to it " + "have recently been unloaded");
}
} else if (localData.getBundles().size() == 1) {
log.warn("HIGH USAGE WARNING : Sole namespace bundle {} is overloading broker {}. " + "No Load Shedding will be done on this broker", localData.getBundles().iterator().next(), broker);
} else {
log.warn("Broker {} is overloaded despite having no bundles", broker);
}
}
}
return selectedBundlesCache;
}
use of org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData in project incubator-pulsar by apache.
the class LeastLongTermMessageRate method selectBroker.
/**
* Find a suitable broker to assign the given bundle to.
*
* @param candidates
* The candidates for which the bundle may be assigned.
* @param bundleToAssign
* The data for the bundle to assign.
* @param loadData
* The load data from the leader broker.
* @param conf
* The service configuration.
* @return The name of the selected broker as it appears on ZooKeeper.
*/
@Override
public Optional<String> selectBroker(final Set<String> candidates, final BundleData bundleToAssign, final LoadData loadData, final ServiceConfiguration conf) {
bestBrokers.clear();
double minScore = Double.POSITIVE_INFINITY;
// select one of them at the end.
for (String broker : candidates) {
final BrokerData brokerData = loadData.getBrokerData().get(broker);
final double score = getScore(brokerData, conf);
if (score == Double.POSITIVE_INFINITY) {
final LocalBrokerData localData = brokerData.getLocalData();
log.warn("Broker {} is overloaded: CPU: {}%, MEMORY: {}%, DIRECT MEMORY: {}%, BANDWIDTH IN: {}%, " + "BANDWIDTH OUT: {}%", broker, localData.getCpu().percentUsage(), localData.getMemory().percentUsage(), localData.getDirectMemory().percentUsage(), localData.getBandwidthIn().percentUsage(), localData.getBandwidthOut().percentUsage());
}
if (score < minScore) {
// Clear best brokers since this score beats the other brokers.
bestBrokers.clear();
bestBrokers.add(broker);
minScore = score;
} else if (score == minScore) {
// Add this broker to best brokers since it ties with the best score.
bestBrokers.add(broker);
}
}
if (bestBrokers.isEmpty()) {
// All brokers are overloaded.
// Assign randomly in this case.
bestBrokers.addAll(candidates);
}
if (bestBrokers.isEmpty()) {
// If still, it means there are no available brokers at this point
return Optional.empty();
}
return Optional.of(bestBrokers.get(ThreadLocalRandom.current().nextInt(bestBrokers.size())));
}
use of org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData in project incubator-pulsar by apache.
the class LookupDataTest method testLoadReportSerialization.
@Test
public void testLoadReportSerialization() throws Exception {
final String simpleLmBrokerUrl = "simple";
final String simpleLmReportName = "simpleLoadManager";
final String modularLmBrokerUrl = "modular";
final SystemResourceUsage simpleLmSystemResourceUsage = new SystemResourceUsage();
final ResourceUsage resource = new ResourceUsage();
final double usage = 55.0;
resource.usage = usage;
simpleLmSystemResourceUsage.bandwidthIn = resource;
LoadReport simpleReport = getSimpleLoadManagerLoadReport(simpleLmBrokerUrl, simpleLmReportName, simpleLmSystemResourceUsage);
LocalBrokerData modularReport = getModularLoadManagerLoadReport(modularLmBrokerUrl, resource);
LoadManagerReport simpleLoadReport = ObjectMapperFactory.getThreadLocal().readValue(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(simpleReport), LoadManagerReport.class);
LoadManagerReport modularLoadReport = ObjectMapperFactory.getThreadLocal().readValue(ObjectMapperFactory.getThreadLocal().writeValueAsBytes(modularReport), LoadManagerReport.class);
assertEquals(simpleLoadReport.getWebServiceUrl(), simpleLmBrokerUrl);
assertTrue(simpleLoadReport instanceof LoadReport);
assertEquals(((LoadReport) simpleLoadReport).getName(), simpleLmReportName);
assertEquals(((LoadReport) simpleLoadReport).getSystemResourceUsage().bandwidthIn.usage, usage);
assertEquals(modularLoadReport.getWebServiceUrl(), modularLmBrokerUrl);
assertTrue(modularLoadReport instanceof LocalBrokerData);
assertEquals(((LocalBrokerData) modularLoadReport).getBandwidthIn().usage, usage);
}
use of org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData in project incubator-pulsar by apache.
the class BrokerMonitor method printGlobalData.
// Prints out the global load data.
private void printGlobalData() {
synchronized (loadData) {
// 1 header row, 1 total row, and loadData.size() rows for brokers.
Object[][] rows = new Object[loadData.size() + 2][];
rows[0] = GLOBAL_HEADER;
int totalBundles = 0;
double totalThroughput = 0;
double totalMessageRate = 0;
double totalLongTermMessageRate = 0;
double maxMaxUsage = 0;
int i = 1;
for (final Map.Entry<String, Object> entry : loadData.entrySet()) {
final String broker = entry.getKey();
final Object data = entry.getValue();
rows[i] = new Object[GLOBAL_HEADER.length];
rows[i][0] = broker;
int numBundles;
double messageRate;
double longTermMessageRate;
double messageThroughput;
double maxUsage;
if (data instanceof LoadReport) {
final LoadReport loadReport = (LoadReport) data;
numBundles = (int) loadReport.getNumBundles();
messageRate = loadReport.getMsgRateIn() + loadReport.getMsgRateOut();
longTermMessageRate = loadReport.getAllocatedMsgRateIn() + loadReport.getAllocatedMsgRateOut();
messageThroughput = (loadReport.getAllocatedBandwidthIn() + loadReport.getAllocatedBandwidthOut()) / 1024;
final SystemResourceUsage systemResourceUsage = loadReport.getSystemResourceUsage();
maxUsage = Math.max(Math.max(Math.max(systemResourceUsage.getCpu().percentUsage(), systemResourceUsage.getMemory().percentUsage()), Math.max(systemResourceUsage.getDirectMemory().percentUsage(), systemResourceUsage.getBandwidthIn().percentUsage())), systemResourceUsage.getBandwidthOut().percentUsage());
} else if (data instanceof LocalBrokerData) {
final LocalBrokerData localData = (LocalBrokerData) data;
numBundles = localData.getNumBundles();
messageRate = localData.getMsgRateIn() + localData.getMsgRateOut();
final String timeAveragePath = ModularLoadManagerImpl.TIME_AVERAGE_BROKER_ZPATH + "/" + broker;
try {
final TimeAverageBrokerData timeAverageData = gson.fromJson(new String(zkClient.getData(timeAveragePath, false, null)), TimeAverageBrokerData.class);
longTermMessageRate = timeAverageData.getLongTermMsgRateIn() + timeAverageData.getLongTermMsgRateOut();
} catch (Exception x) {
throw new RuntimeException(x);
}
messageThroughput = (localData.getMsgThroughputIn() + localData.getMsgThroughputOut()) / 1024;
maxUsage = localData.getMaxResourceUsage();
} else {
throw new AssertionError("Unreachable code");
}
rows[i][1] = numBundles;
rows[i][2] = messageRate;
rows[i][3] = messageThroughput;
rows[i][4] = longTermMessageRate;
rows[i][5] = maxUsage;
totalBundles += numBundles;
totalMessageRate += messageRate;
totalLongTermMessageRate += longTermMessageRate;
totalThroughput += messageThroughput;
maxMaxUsage = Math.max(maxUsage, maxMaxUsage);
++i;
}
final int finalRow = loadData.size() + 1;
rows[finalRow] = new Object[GLOBAL_HEADER.length];
rows[finalRow][0] = "TOTAL";
rows[finalRow][1] = totalBundles;
rows[finalRow][2] = totalMessageRate;
rows[finalRow][3] = totalLongTermMessageRate;
rows[finalRow][4] = totalThroughput;
rows[finalRow][5] = maxMaxUsage;
final String table = globalTableMaker.make(rows);
log.info("Overall Broker Data:\n{}", table);
}
}
Aggregations