Search in sources :

Example 1 with BundleData

use of org.apache.pulsar.broker.BundleData 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;
}
Also used : ResourceQuota(org.apache.pulsar.common.policies.data.ResourceQuota) TimeAverageMessageData(org.apache.pulsar.broker.TimeAverageMessageData) BundleData(org.apache.pulsar.broker.BundleData) BrokerFilterException(org.apache.pulsar.broker.loadbalance.BrokerFilterException) KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException) NoNodeException(org.apache.zookeeper.KeeperException.NoNodeException) PulsarServerException(org.apache.pulsar.broker.PulsarServerException)

Example 2 with BundleData

use of org.apache.pulsar.broker.BundleData 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);
        }
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) BrokerData(org.apache.pulsar.broker.BrokerData) TimeAverageBrokerData(org.apache.pulsar.broker.TimeAverageBrokerData) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) BundleData(org.apache.pulsar.broker.BundleData) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 3 with BundleData

use of org.apache.pulsar.broker.BundleData 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;
}
Also used : LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) BrokerData(org.apache.pulsar.broker.BrokerData) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) TimeAverageMessageData(org.apache.pulsar.broker.TimeAverageMessageData) Map(java.util.Map) HashMap(java.util.HashMap) BundleData(org.apache.pulsar.broker.BundleData)

Example 4 with BundleData

use of org.apache.pulsar.broker.BundleData 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;
}
Also used : TimeAverageMessageData(org.apache.pulsar.broker.TimeAverageMessageData) BundleData(org.apache.pulsar.broker.BundleData) TimeAverageBrokerData(org.apache.pulsar.broker.TimeAverageBrokerData)

Example 5 with BundleData

use of org.apache.pulsar.broker.BundleData in project incubator-pulsar by apache.

the class LoadSimulationController method handleCopy.

// Handle the command line arguments associated with the copy command.
private void handleCopy(final ShellArguments arguments) throws Exception {
    final List<String> commandArguments = arguments.commandArguments;
    // Copy accepts 3 application arguments: Tenant name, source ZooKeeper and target ZooKeeper connect strings.
    if (checkAppArgs(commandArguments.size() - 1, 3)) {
        final String tenantName = commandArguments.get(1);
        final String sourceZKConnectString = commandArguments.get(2);
        final String targetZKConnectString = commandArguments.get(3);
        final ZooKeeper sourceZKClient = new ZooKeeper(sourceZKConnectString, 5000, null);
        final ZooKeeper targetZKClient = new ZooKeeper(targetZKConnectString, 5000, null);
        // Make a map for each thread to speed up the ZooKeeper writing process.
        final Map<String, ResourceQuota>[] threadLocalMaps = new Map[clients.length];
        for (int i = 0; i < clients.length; ++i) {
            threadLocalMaps[i] = new HashMap<>();
        }
        getResourceQuotas(QUOTA_ROOT, sourceZKClient, threadLocalMaps);
        final List<Future> futures = new ArrayList<>(clients.length);
        int i = 0;
        log.info("Copying...");
        for (final Map<String, ResourceQuota> bundleToQuota : threadLocalMaps) {
            final int j = i;
            futures.add(threadPool.submit(() -> {
                for (final Map.Entry<String, ResourceQuota> entry : bundleToQuota.entrySet()) {
                    final String bundle = entry.getKey();
                    final ResourceQuota quota = entry.getValue();
                    // Simulation will send messages in and out at about the same rate, so just make the rate the
                    // average of in and out.
                    final int tenantStart = QUOTA_ROOT.length() + 1;
                    final int clusterStart = bundle.indexOf('/', tenantStart) + 1;
                    final String sourceTenant = bundle.substring(tenantStart, clusterStart - 1);
                    final int namespaceStart = bundle.indexOf('/', clusterStart) + 1;
                    final String sourceCluster = bundle.substring(clusterStart, namespaceStart - 1);
                    final String namespace = bundle.substring(namespaceStart, bundle.lastIndexOf('/'));
                    final String keyRangeString = bundle.substring(bundle.lastIndexOf('/') + 1);
                    // To prevent duplicate node issues for same namespace names in different clusters/tenants.
                    final String manglePrefix = String.format("%s-%s-%s", sourceCluster, sourceTenant, keyRangeString);
                    final String mangledNamespace = String.format("%s-%s", manglePrefix, namespace);
                    final BundleData bundleData = initializeBundleData(quota, arguments);
                    final String oldAPITargetPath = String.format("/loadbalance/resource-quota/namespace/%s/%s/%s/0x00000000_0xffffffff", tenantName, cluster, mangledNamespace);
                    final String newAPITargetPath = String.format("/loadbalance/bundle-data/%s/%s/%s/0x00000000_0xffffffff", tenantName, cluster, mangledNamespace);
                    try {
                        ZkUtils.createFullPathOptimistic(targetZKClient, oldAPITargetPath, ObjectMapperFactory.getThreadLocal().writeValueAsBytes(quota), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                    } catch (KeeperException.NodeExistsException e) {
                    // Ignore already created nodes.
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    // Put the bundle data in the new ZooKeeper.
                    try {
                        ZkUtils.createFullPathOptimistic(targetZKClient, newAPITargetPath, bundleData.getJsonBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                    } catch (KeeperException.NodeExistsException e) {
                    // Ignore already created nodes.
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                    try {
                        trade(arguments, makeTopic(tenantName, mangledNamespace, "t"), j);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }));
            ++i;
        }
        for (final Future future : futures) {
            future.get();
        }
        sourceZKClient.close();
        targetZKClient.close();
    }
}
Also used : ArrayList(java.util.ArrayList) BundleData(org.apache.pulsar.broker.BundleData) ParameterException(com.beust.jcommander.ParameterException) KeeperException(org.apache.zookeeper.KeeperException) ZooKeeper(org.apache.zookeeper.ZooKeeper) ResourceQuota(org.apache.pulsar.common.policies.data.ResourceQuota) Future(java.util.concurrent.Future) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

BundleData (org.apache.pulsar.broker.BundleData)12 HashMap (java.util.HashMap)6 Map (java.util.Map)6 TimeAverageMessageData (org.apache.pulsar.broker.TimeAverageMessageData)6 BrokerData (org.apache.pulsar.broker.BrokerData)5 TimeAverageBrokerData (org.apache.pulsar.broker.TimeAverageBrokerData)5 LocalBrokerData (org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData)5 KeeperException (org.apache.zookeeper.KeeperException)5 ResourceQuota (org.apache.pulsar.common.policies.data.ResourceQuota)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)3 PulsarServerException (org.apache.pulsar.broker.PulsarServerException)3 BrokerFilterException (org.apache.pulsar.broker.loadbalance.BrokerFilterException)3 NamespaceBundleStats (org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats)3 NoNodeException (org.apache.zookeeper.KeeperException.NoNodeException)3 ZooKeeper (org.apache.zookeeper.ZooKeeper)3 Test (org.testng.annotations.Test)3 ParameterException (com.beust.jcommander.ParameterException)2 HashSet (java.util.HashSet)2