use of org.apache.pulsar.broker.TimeAverageMessageData in project incubator-pulsar by apache.
the class ModularLoadManagerImpl method getBundleDataOrDefault.
// Attempt to local the data for the given bundle in ZooKeeper.
// If it cannot be found, return the default bundle data.
private BundleData getBundleDataOrDefault(final String bundle) {
BundleData bundleData = null;
try {
final String bundleZPath = getBundleDataZooKeeperPath(bundle);
final String quotaZPath = String.format("%s/%s", RESOURCE_QUOTA_ZPATH, bundle);
if (zkClient.exists(bundleZPath, null) != null) {
bundleData = readJson(zkClient.getData(bundleZPath, null, null), BundleData.class);
} else if (zkClient.exists(quotaZPath, null) != null) {
final ResourceQuota quota = readJson(zkClient.getData(quotaZPath, null, null), ResourceQuota.class);
bundleData = new BundleData(NUM_SHORT_SAMPLES, NUM_LONG_SAMPLES);
// Initialize from existing resource quotas if new API ZNodes do not exist.
final TimeAverageMessageData shortTermData = bundleData.getShortTermData();
final TimeAverageMessageData longTermData = bundleData.getLongTermData();
shortTermData.setMsgRateIn(quota.getMsgRateIn());
shortTermData.setMsgRateOut(quota.getMsgRateOut());
shortTermData.setMsgThroughputIn(quota.getBandwidthIn());
shortTermData.setMsgThroughputOut(quota.getBandwidthOut());
longTermData.setMsgRateIn(quota.getMsgRateIn());
longTermData.setMsgRateOut(quota.getMsgRateOut());
longTermData.setMsgThroughputIn(quota.getBandwidthIn());
longTermData.setMsgThroughputOut(quota.getBandwidthOut());
// Assume ample history.
shortTermData.setNumSamples(NUM_SHORT_SAMPLES);
longTermData.setNumSamples(NUM_LONG_SAMPLES);
}
} catch (Exception e) {
log.warn("Error when trying to find bundle {} on zookeeper: {}", bundle, e);
}
if (bundleData == null) {
bundleData = new BundleData(NUM_SHORT_SAMPLES, NUM_LONG_SAMPLES, defaultStats);
}
return bundleData;
}
use of org.apache.pulsar.broker.TimeAverageMessageData 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.broker.TimeAverageMessageData in project incubator-pulsar by apache.
the class LeastLongTermMessageRate method getScore.
// Form a score for a broker using its preallocated bundle data and time average data.
// This is done by summing all preallocated long-term message rates and adding them to the broker's overall
// long-term message rate, which is itself the sum of the long-term message rate of every allocated bundle.
// Any broker at (or above) the overload threshold will have a score of POSITIVE_INFINITY.
private static double getScore(final BrokerData brokerData, final ServiceConfiguration conf) {
final double overloadThreshold = conf.getLoadBalancerBrokerOverloadedThresholdPercentage() / 100.0;
final double maxUsage = brokerData.getLocalData().getMaxResourceUsage();
if (maxUsage > overloadThreshold) {
log.warn("Broker {} is overloaded: max usage={}", brokerData.getLocalData().getWebServiceUrl(), maxUsage);
return Double.POSITIVE_INFINITY;
}
double totalMessageRate = 0;
for (BundleData bundleData : brokerData.getPreallocatedBundleData().values()) {
final TimeAverageMessageData longTermData = bundleData.getLongTermData();
totalMessageRate += longTermData.getMsgRateIn() + longTermData.getMsgRateOut();
}
// calculate estimated score
final TimeAverageBrokerData timeAverageData = brokerData.getTimeAverageData();
final double timeAverageLongTermMessageRate = timeAverageData.getLongTermMsgRateIn() + timeAverageData.getLongTermMsgRateOut();
final double totalMessageRateEstimate = totalMessageRate + timeAverageLongTermMessageRate;
if (log.isDebugEnabled()) {
log.debug("Broker {} has long term message rate {}", brokerData.getLocalData().getWebServiceUrl(), totalMessageRateEstimate);
}
return totalMessageRateEstimate;
}
use of org.apache.pulsar.broker.TimeAverageMessageData in project incubator-pulsar by apache.
the class ModularLoadManagerImplTest method testEvenBundleDistribution.
// Test that bundles belonging to the same namespace are distributed evenly among brokers.
// Test disabled since it's depending on CPU usage in the machine
@Test(enabled = false)
public void testEvenBundleDistribution() throws Exception {
final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", "test", 16);
int numAssignedToPrimary = 0;
int numAssignedToSecondary = 0;
final BundleData bundleData = new BundleData(10, 1000);
final TimeAverageMessageData longTermMessageData = new TimeAverageMessageData(1000);
longTermMessageData.setMsgRateIn(1000);
bundleData.setLongTermData(longTermMessageData);
final String firstBundleDataPath = String.format("%s/%s", ModularLoadManagerImpl.BUNDLE_DATA_ZPATH, bundles[0]);
// Write long message rate for first bundle to ensure that even bundle distribution is not a coincidence of
// balancing by message rate. If we were balancing by message rate, one of the brokers should only have this
// one bundle.
ZkUtils.createFullPathOptimistic(pulsar1.getZkClient(), firstBundleDataPath, bundleData.getJsonBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
for (final NamespaceBundle bundle : bundles) {
if (primaryLoadManager.selectBrokerForAssignment(bundle).equals(primaryHost)) {
++numAssignedToPrimary;
} else {
++numAssignedToSecondary;
}
if ((numAssignedToPrimary + numAssignedToSecondary) % 2 == 0) {
// On even number of assignments, assert that an equal number of bundles have been assigned between
// them.
assertEquals(numAssignedToPrimary, numAssignedToSecondary);
}
}
}
use of org.apache.pulsar.broker.TimeAverageMessageData in project incubator-pulsar by apache.
the class ModularLoadManagerImplTest method testMaxTopicDistributionToBroker.
/**
* It verifies that once broker owns max-number of topics: load-manager doesn't allocates new bundles to that broker
* unless all the brokers are in same state.
*
* <pre>
* 1. Create a bundle whose bundle-resource-quota will contain max-topics
* 2. Load-manager assigns broker to this bundle so, assigned broker is overloaded with max-topics
* 3. For any new further bundles: broker assigns different brokers.
* </pre>
*
* @throws Exception
*/
@Test
public void testMaxTopicDistributionToBroker() throws Exception {
final int totalBundles = 50;
final NamespaceBundle[] bundles = LoadBalancerTestingUtils.makeBundles(nsFactory, "test", "test", "test", totalBundles);
final BundleData bundleData = new BundleData(10, 1000);
// it sets max topics under this bundle so, owner of this broker reaches max-topic threshold
bundleData.setTopics(pulsar1.getConfiguration().getLoadBalancerBrokerMaxTopics() + 10);
final TimeAverageMessageData longTermMessageData = new TimeAverageMessageData(1000);
longTermMessageData.setMsgRateIn(1000);
bundleData.setLongTermData(longTermMessageData);
final String firstBundleDataPath = String.format("%s/%s", ModularLoadManagerImpl.BUNDLE_DATA_ZPATH, bundles[0]);
ZkUtils.createFullPathOptimistic(pulsar1.getZkClient(), firstBundleDataPath, bundleData.getJsonBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
String maxTopicOwnedBroker = primaryLoadManager.selectBrokerForAssignment(bundles[0]).get();
for (int i = 1; i < totalBundles; i++) {
assertNotEquals(primaryLoadManager.selectBrokerForAssignment(bundles[i]), maxTopicOwnedBroker);
}
}
Aggregations