use of org.apache.pulsar.broker.BrokerData in project incubator-pulsar by apache.
the class ModularLoadManagerImpl method updateBundleData.
// As the leader broker, use the local broker data saved on ZooKeeper to update the bundle stats so that better load
// management decisions may be made.
private void updateBundleData() {
final Map<String, BundleData> bundleData = loadData.getBundleData();
// Iterate over the broker data.
for (Map.Entry<String, BrokerData> brokerEntry : loadData.getBrokerData().entrySet()) {
final String broker = brokerEntry.getKey();
final BrokerData brokerData = brokerEntry.getValue();
final Map<String, NamespaceBundleStats> statsMap = brokerData.getLocalData().getLastStats();
// broker to update the bundle data.
for (Map.Entry<String, NamespaceBundleStats> entry : statsMap.entrySet()) {
final String bundle = entry.getKey();
final NamespaceBundleStats stats = entry.getValue();
if (bundleData.containsKey(bundle)) {
// If we recognize the bundle, add these stats as a new
// sample.
bundleData.get(bundle).update(stats);
} else {
// Otherwise, attempt to find the bundle data on ZooKeeper.
// If it cannot be found, use the latest stats as the first
// sample.
BundleData currentBundleData = getBundleDataOrDefault(bundle);
currentBundleData.update(stats);
bundleData.put(bundle, currentBundleData);
}
}
// Remove all loaded bundles from the preallocated maps.
final Map<String, BundleData> preallocatedBundleData = brokerData.getPreallocatedBundleData();
synchronized (preallocatedBundleData) {
for (String preallocatedBundleName : brokerData.getPreallocatedBundleData().keySet()) {
if (brokerData.getLocalData().getBundles().contains(preallocatedBundleName)) {
final Iterator<Map.Entry<String, BundleData>> preallocatedIterator = preallocatedBundleData.entrySet().iterator();
while (preallocatedIterator.hasNext()) {
final String bundle = preallocatedIterator.next().getKey();
if (bundleData.containsKey(bundle)) {
preallocatedIterator.remove();
preallocatedBundleToBroker.remove(bundle);
}
}
}
// This is needed too in case a broker which was assigned a bundle dies and comes back up.
if (preallocatedBundleToBroker.containsKey(preallocatedBundleName)) {
preallocatedBundleToBroker.remove(preallocatedBundleName);
}
}
}
// Using the newest data, update the aggregated time-average data for the current broker.
brokerData.getTimeAverageData().reset(statsMap.keySet(), bundleData, defaultStats);
final Map<String, Set<String>> namespaceToBundleRange = brokerToNamespaceToBundleRange.computeIfAbsent(broker, k -> new HashMap<>());
synchronized (namespaceToBundleRange) {
namespaceToBundleRange.clear();
LoadManagerShared.fillNamespaceToBundlesMap(statsMap.keySet(), namespaceToBundleRange);
LoadManagerShared.fillNamespaceToBundlesMap(preallocatedBundleData.keySet(), namespaceToBundleRange);
}
}
}
use of org.apache.pulsar.broker.BrokerData 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.broker.BrokerData 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.BrokerData in project incubator-pulsar by apache.
the class BrokerVersionFilter method filter.
/**
* From the given set of available broker candidates, filter those using the version numbers.
*
* @param brokers
* The currently available brokers that have not already been filtered.
* @param bundleToAssign
* The data for the bundle to assign.
* @param loadData
* The load data from the leader broker.
* @param conf
* The service configuration.
*/
public void filter(Set<String> brokers, BundleData bundleToAssign, LoadData loadData, ServiceConfiguration conf) throws BrokerFilterBadVersionException {
if (!conf.isPreferLaterVersions()) {
return;
}
com.github.zafarkhaja.semver.Version latestVersion = null;
try {
latestVersion = getLatestVersionNumber(brokers, loadData);
LOG.info("Latest broker version found was [{}]", latestVersion);
} catch (Exception x) {
LOG.warn("Disabling PreferLaterVersions feature; reason: " + x.getMessage());
throw new BrokerFilterBadVersionException("Cannot determine newest broker version: " + x.getMessage());
}
int numBrokersLatestVersion = 0;
int numBrokersOlderVersion = 0;
Iterator<String> brokerIterator = brokers.iterator();
while (brokerIterator.hasNext()) {
String broker = brokerIterator.next();
BrokerData data = loadData.getBrokerData().get(broker);
String brokerVersion = data.getLocalData().getBrokerVersionString();
com.github.zafarkhaja.semver.Version brokerVersionVersion = Version.valueOf(brokerVersion);
if (brokerVersionVersion.equals(latestVersion)) {
LOG.debug("Broker [{}] is running the latest version ([{}])", broker, brokerVersion);
++numBrokersLatestVersion;
} else {
LOG.info("Broker [{}] is running an older version ([{}]); latest version is [{}]", broker, brokerVersion, latestVersion);
++numBrokersOlderVersion;
brokerIterator.remove();
}
}
if (numBrokersOlderVersion == 0) {
LOG.info("All {} brokers are running the latest version [{}]", numBrokersLatestVersion, latestVersion);
}
}
use of org.apache.pulsar.broker.BrokerData 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())));
}
Aggregations