Search in sources :

Example 6 with NamespaceBundleStats

use of org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats in project incubator-pulsar by apache.

the class ModularLoadManagerImplTest method testLoadShedding.

// Test that load shedding works
@Test
public void testLoadShedding() throws Exception {
    final NamespaceBundleStats stats1 = new NamespaceBundleStats();
    final NamespaceBundleStats stats2 = new NamespaceBundleStats();
    stats1.msgRateIn = 100;
    stats2.msgRateIn = 200;
    final Map<String, NamespaceBundleStats> statsMap = new ConcurrentHashMap<>();
    statsMap.put(mockBundleName(1), stats1);
    statsMap.put(mockBundleName(2), stats2);
    final LocalBrokerData localBrokerData = new LocalBrokerData();
    localBrokerData.update(new SystemResourceUsage(), statsMap);
    final Namespaces namespacesSpy1 = spy(pulsar1.getAdminClient().namespaces());
    AtomicReference<String> bundleReference = new AtomicReference<>();
    doAnswer(invocation -> {
        bundleReference.set(invocation.getArguments()[0].toString() + '/' + invocation.getArguments()[1]);
        return null;
    }).when(namespacesSpy1).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    setField(pulsar1.getAdminClient(), "namespaces", namespacesSpy1);
    pulsar1.getConfiguration().setLoadBalancerEnabled(true);
    final LoadData loadData = (LoadData) getField(primaryLoadManager, "loadData");
    final Map<String, BrokerData> brokerDataMap = loadData.getBrokerData();
    final BrokerData brokerDataSpy1 = spy(brokerDataMap.get(primaryHost));
    when(brokerDataSpy1.getLocalData()).thenReturn(localBrokerData);
    brokerDataMap.put(primaryHost, brokerDataSpy1);
    // Need to update all the bundle data for the shedder to see the spy.
    primaryLoadManager.onUpdate(null, null, null);
    Thread.sleep(100);
    localBrokerData.setCpu(new ResourceUsage(80, 100));
    primaryLoadManager.doLoadShedding();
    // 80% is below overload threshold: verify nothing is unloaded.
    verify(namespacesSpy1, Mockito.times(0)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    localBrokerData.getCpu().usage = 90;
    primaryLoadManager.doLoadShedding();
    // Most expensive bundle will be unloaded.
    verify(namespacesSpy1, Mockito.times(1)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    assertEquals(bundleReference.get(), mockBundleName(2));
    primaryLoadManager.doLoadShedding();
    // Now less expensive bundle will be unloaded (normally other bundle would move off and nothing would be
    // unloaded, but this is not the case due to the spy's behavior).
    verify(namespacesSpy1, Mockito.times(2)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
    assertEquals(bundleReference.get(), mockBundleName(1));
    primaryLoadManager.doLoadShedding();
    // Now both are in grace period: neither should be unloaded.
    verify(namespacesSpy1, Mockito.times(2)).unloadNamespaceBundle(Mockito.anyString(), Mockito.anyString());
}
Also used : Namespaces(org.apache.pulsar.client.admin.Namespaces) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) BrokerData(org.apache.pulsar.broker.BrokerData) LocalBrokerData(org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData) SystemResourceUsage(org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage) ResourceUsage(org.apache.pulsar.policies.data.loadbalancer.ResourceUsage) SystemResourceUsage(org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage) AtomicReference(java.util.concurrent.atomic.AtomicReference) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Test(org.testng.annotations.Test)

Example 7 with NamespaceBundleStats

use of org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats in project incubator-pulsar by apache.

the class SimpleLoadManagerImplTest method testNamespaceBundleStats.

@Test
public void testNamespaceBundleStats() {
    NamespaceBundleStats nsb1 = new NamespaceBundleStats();
    nsb1.msgRateOut = 10000;
    nsb1.producerCount = 1;
    nsb1.consumerCount = 1;
    nsb1.cacheSize = 4;
    nsb1.msgRateIn = 500;
    nsb1.msgThroughputIn = 30;
    nsb1.msgThroughputOut = 30;
    NamespaceBundleStats nsb2 = new NamespaceBundleStats();
    nsb2.msgRateOut = 20000;
    nsb2.producerCount = 300;
    nsb2.consumerCount = 300;
    nsb2.cacheSize = 110000;
    nsb2.msgRateIn = 5000;
    nsb2.msgThroughputIn = 110000.0;
    nsb2.msgThroughputOut = 110000.0;
    assertTrue(nsb1.compareTo(nsb2) == -1);
    assertTrue(nsb1.compareByMsgRate(nsb2) == -1);
    assertTrue(nsb1.compareByTopicConnections(nsb2) == -1);
    assertTrue(nsb1.compareByCacheSize(nsb2) == -1);
    assertTrue(nsb1.compareByBandwidthOut(nsb2) == -1);
    assertTrue(nsb1.compareByBandwidthIn(nsb2) == -1);
}
Also used : NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) Test(org.testng.annotations.Test)

Example 8 with NamespaceBundleStats

use of org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats in project incubator-pulsar by apache.

the class LoadSimulationController method initializeBundleData.

// Initialize a BundleData from a resource quota and configurations and modify the quota accordingly.
private BundleData initializeBundleData(final ResourceQuota quota, final ShellArguments arguments) {
    final double messageRate = (quota.getMsgRateIn() + quota.getMsgRateOut()) / 2;
    final int messageSize = (int) Math.ceil((quota.getBandwidthIn() + quota.getBandwidthOut()) / (2 * messageRate));
    arguments.rate = messageRate * arguments.rateMultiplier;
    arguments.size = messageSize;
    final NamespaceBundleStats startingStats = new NamespaceBundleStats();
    // Modify the original quota so that new rates are set.
    final double modifiedRate = messageRate * arguments.rateMultiplier;
    final double modifiedBandwidth = (quota.getBandwidthIn() + quota.getBandwidthOut()) * arguments.rateMultiplier / 2;
    quota.setMsgRateIn(modifiedRate);
    quota.setMsgRateOut(modifiedRate);
    quota.setBandwidthIn(modifiedBandwidth);
    quota.setBandwidthOut(modifiedBandwidth);
    // Assume modified memory usage is comparable to the rate multiplier times the original usage.
    quota.setMemory(quota.getMemory() * arguments.rateMultiplier);
    startingStats.msgRateIn = quota.getMsgRateIn();
    startingStats.msgRateOut = quota.getMsgRateOut();
    startingStats.msgThroughputIn = quota.getBandwidthIn();
    startingStats.msgThroughputOut = quota.getBandwidthOut();
    final BundleData bundleData = new BundleData(10, 1000, startingStats);
    // Assume there is ample history for the bundle.
    bundleData.getLongTermData().setNumSamples(1000);
    bundleData.getShortTermData().setNumSamples(10);
    return bundleData;
}
Also used : NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) BundleData(org.apache.pulsar.broker.BundleData)

Example 9 with NamespaceBundleStats

use of org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats in project incubator-pulsar by apache.

the class SimpleLoadManagerImpl method doLoadShedding.

@Override
public void doLoadShedding() {
    long overloadThreshold = this.getLoadBalancerBrokerOverloadedThresholdPercentage();
    long comfortLoadLevel = this.getLoadBalancerBrokerComfortLoadThresholdPercentage();
    log.info("Running load shedding task as leader broker, overload threshold {}, comfort loadlevel {}", overloadThreshold, comfortLoadLevel);
    // overloadedRU --> bundleName
    Map<ResourceUnit, String> namespaceBundlesToBeUnloaded = new HashMap<>();
    synchronized (currentLoadReports) {
        for (Map.Entry<ResourceUnit, LoadReport> entry : currentLoadReports.entrySet()) {
            ResourceUnit overloadedRU = entry.getKey();
            LoadReport lr = entry.getValue();
            if (isAboveLoadLevel(lr.getSystemResourceUsage(), overloadThreshold)) {
                ResourceType bottleneckResourceType = lr.getBottleneckResourceType();
                Map<String, NamespaceBundleStats> bundleStats = lr.getSortedBundleStats(bottleneckResourceType);
                if (bundleStats == null) {
                    log.warn("Null bundle stats for bundle {}", lr.getName());
                    continue;
                }
                // 1. owns only one namespace
                if (bundleStats.size() == 1) {
                    // can't unload one namespace, just issue a warning message
                    String bundleName = lr.getBundleStats().keySet().iterator().next();
                    log.warn("HIGH USAGE WARNING : Sole namespace bundle {} is overloading broker {}. " + "No Load Shedding will be done on this broker", bundleName, overloadedRU.getResourceId());
                    continue;
                }
                for (Map.Entry<String, NamespaceBundleStats> bundleStat : bundleStats.entrySet()) {
                    String bundleName = bundleStat.getKey();
                    NamespaceBundleStats stats = bundleStat.getValue();
                    // We need at least one underloaded RU from list of candidates that can host this bundle
                    if (isBrokerAvailableForRebalancing(bundleStat.getKey(), comfortLoadLevel)) {
                        log.info("Namespace bundle {} will be unloaded from overloaded broker {}, bundle stats (topics: {}, producers {}, " + "consumers {}, bandwidthIn {}, bandwidthOut {})", bundleName, overloadedRU.getResourceId(), stats.topics, stats.producerCount, stats.consumerCount, stats.msgThroughputIn, stats.msgThroughputOut);
                        namespaceBundlesToBeUnloaded.put(overloadedRU, bundleName);
                    } else {
                        log.info("Unable to shed load from broker {}, no brokers with enough capacity available " + "for re-balancing {}", overloadedRU.getResourceId(), bundleName);
                    }
                    break;
                }
            }
        }
    }
    unloadNamespacesFromOverLoadedBrokers(namespaceBundlesToBeUnloaded);
}
Also used : ResourceUnit(org.apache.pulsar.broker.loadbalance.ResourceUnit) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) HashMap(java.util.HashMap) LoadReport(org.apache.pulsar.policies.data.loadbalancer.LoadReport) ResourceType(org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage.ResourceType) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap)

Example 10 with NamespaceBundleStats

use of org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats in project incubator-pulsar by apache.

the class SimpleLoadManagerImpl method doNamespaceBundleSplit.

/**
 * Detect and split hot namespace bundles
 */
@Override
public void doNamespaceBundleSplit() throws Exception {
    int maxBundleCount = pulsar.getConfiguration().getLoadBalancerNamespaceMaximumBundles();
    long maxBundleTopics = pulsar.getConfiguration().getLoadBalancerNamespaceBundleMaxTopics();
    long maxBundleSessions = pulsar.getConfiguration().getLoadBalancerNamespaceBundleMaxSessions();
    long maxBundleMsgRate = pulsar.getConfiguration().getLoadBalancerNamespaceBundleMaxMsgRate();
    long maxBundleBandwidth = pulsar.getConfiguration().getLoadBalancerNamespaceBundleMaxBandwidthMbytes() * MBytes;
    log.info("Running namespace bundle split with thresholds: topics {}, sessions {}, msgRate {}, bandwidth {}, maxBundles {}", maxBundleTopics, maxBundleSessions, maxBundleMsgRate, maxBundleBandwidth, maxBundleCount);
    if (this.lastLoadReport == null || this.lastLoadReport.getBundleStats() == null) {
        return;
    }
    Map<String, NamespaceBundleStats> bundleStats = this.lastLoadReport.getBundleStats();
    Set<String> bundlesToBeSplit = new HashSet<>();
    for (Map.Entry<String, NamespaceBundleStats> statsEntry : bundleStats.entrySet()) {
        String bundleName = statsEntry.getKey();
        NamespaceBundleStats stats = statsEntry.getValue();
        long totalSessions = stats.consumerCount + stats.producerCount;
        double totalMsgRate = stats.msgRateIn + stats.msgRateOut;
        double totalBandwidth = stats.msgThroughputIn + stats.msgThroughputOut;
        boolean needSplit = false;
        if (stats.topics > maxBundleTopics || totalSessions > maxBundleSessions || totalMsgRate > maxBundleMsgRate || totalBandwidth > maxBundleBandwidth) {
            if (stats.topics <= 1) {
                log.info("Unable to split hot namespace bundle {} since there is only one topic.", bundleName);
            } else {
                NamespaceName namespaceName = NamespaceName.get(LoadManagerShared.getNamespaceNameFromBundleName(bundleName));
                int numBundles = pulsar.getNamespaceService().getBundleCount(namespaceName);
                if (numBundles >= maxBundleCount) {
                    log.info("Unable to split hot namespace bundle {} since the namespace has too many bundles.", bundleName);
                } else {
                    needSplit = true;
                }
            }
        }
        if (needSplit) {
            if (this.getLoadBalancerAutoBundleSplitEnabled()) {
                log.info("Will split hot namespace bundle {}, topics {}, producers+consumers {}, msgRate in+out {}, bandwidth in+out {}", bundleName, stats.topics, totalSessions, totalMsgRate, totalBandwidth);
                bundlesToBeSplit.add(bundleName);
            } else {
                log.info("DRY RUN - split hot namespace bundle {}, topics {}, producers+consumers {}, msgRate in+out {}, bandwidth in+out {}", bundleName, stats.topics, totalSessions, totalMsgRate, totalBandwidth);
            }
        }
    }
    if (bundlesToBeSplit.size() > 0) {
        for (String bundleName : bundlesToBeSplit) {
            try {
                pulsar.getAdminClient().namespaces().splitNamespaceBundle(LoadManagerShared.getNamespaceNameFromBundleName(bundleName), LoadManagerShared.getBundleRangeFromBundleName(bundleName), pulsar.getConfiguration().isLoadBalancerAutoUnloadSplitBundlesEnabled());
                log.info("Successfully split namespace bundle {}", bundleName);
            } catch (Exception e) {
                log.error("Failed to split namespace bundle {}", bundleName, e);
            }
        }
        this.setLoadReportForceUpdateFlag();
    }
}
Also used : KeeperException(org.apache.zookeeper.KeeperException) IOException(java.io.IOException) PulsarServerException(org.apache.pulsar.broker.PulsarServerException) NamespaceName(org.apache.pulsar.common.naming.NamespaceName) NamespaceBundleStats(org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats) Map(java.util.Map) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) HashSet(java.util.HashSet)

Aggregations

NamespaceBundleStats (org.apache.pulsar.policies.data.loadbalancer.NamespaceBundleStats)15 HashMap (java.util.HashMap)8 Map (java.util.Map)7 SystemResourceUsage (org.apache.pulsar.policies.data.loadbalancer.SystemResourceUsage)6 Test (org.testng.annotations.Test)6 LoadReport (org.apache.pulsar.policies.data.loadbalancer.LoadReport)5 TreeMap (java.util.TreeMap)4 ResourceUsage (org.apache.pulsar.policies.data.loadbalancer.ResourceUsage)4 HashSet (java.util.HashSet)3 LocalBrokerData (org.apache.pulsar.policies.data.loadbalancer.LocalBrokerData)3 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 AtomicReference (java.util.concurrent.atomic.AtomicReference)2 BrokerData (org.apache.pulsar.broker.BrokerData)2 BundleData (org.apache.pulsar.broker.BundleData)2 ResourceUnit (org.apache.pulsar.broker.loadbalance.ResourceUnit)2 SimpleResourceUnit (org.apache.pulsar.broker.loadbalance.impl.SimpleResourceUnit)2 ResourceQuota (org.apache.pulsar.common.policies.data.ResourceQuota)2 ByteBuf (io.netty.buffer.ByteBuf)1 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1