use of org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl in project incubator-pulsar by apache.
the class AntiAffinityNamespaceGroupTest method testLoadSheddingWithAntiAffinityNamespace.
/**
* It verifies that load-manager::shouldAntiAffinityNamespaceUnload checks that unloading should only happen if all
* brokers have same number of anti-affinity namespaces
*
* @throws Exception
*/
@Test
public void testLoadSheddingWithAntiAffinityNamespace() throws Exception {
final String namespace = "my-property/use/my-ns";
final int totalNamespaces = 5;
final String namespaceAntiAffinityGroup = "my-antiaffinity";
final String bundle = "0x00000000_0xffffffff";
admin1.properties().createProperty("my-property", new PropertyAdmin(Lists.newArrayList("appid1", "appid2"), Sets.newHashSet("use")));
for (int i = 0; i < totalNamespaces; i++) {
final String ns = namespace + i;
admin1.namespaces().createNamespace(ns);
admin1.namespaces().setNamespaceAntiAffinityGroup(ns, namespaceAntiAffinityGroup);
}
PulsarClient pulsarClient = PulsarClient.builder().serviceUrl(pulsar1.getWebServiceAddress()).build();
Producer<byte[]> producer = pulsarClient.newProducer().topic("persistent://" + namespace + "0/my-topic1").create();
ModularLoadManagerImpl loadManager = (ModularLoadManagerImpl) ((ModularLoadManagerWrapper) pulsar1.getLoadManager().get()).getLoadManager();
pulsar1.getBrokerService().updateRates();
loadManager.updateAll();
assertTrue(loadManager.shouldAntiAffinityNamespaceUnload(namespace + "0", bundle, primaryHost));
producer.close();
pulsarClient.close();
}
use of org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl in project incubator-pulsar by apache.
the class ModularLoadManagerImplTest method testBrokerStopCacheUpdate.
/**
* It verifies that deletion of broker-znode on broker-stop will invalidate availableBrokerCache list
*
* @throws Exception
*/
@Test
public void testBrokerStopCacheUpdate() throws Exception {
String secondaryBroker = pulsar2.getAdvertisedAddress() + ":" + SECONDARY_BROKER_WEBSERVICE_PORT;
pulsar2.getLocalZkCache().getZooKeeper().delete(LoadManager.LOADBALANCE_BROKERS_ROOT + "/" + secondaryBroker, -1);
Thread.sleep(100);
ModularLoadManagerWrapper loadManagerWapper = (ModularLoadManagerWrapper) pulsar1.getLoadManager().get();
Field loadMgrField = ModularLoadManagerWrapper.class.getDeclaredField("loadManager");
loadMgrField.setAccessible(true);
ModularLoadManagerImpl loadManager = (ModularLoadManagerImpl) loadMgrField.get(loadManagerWapper);
Set<String> avaialbeBrokers = loadManager.getAvailableBrokers();
assertEquals(avaialbeBrokers.size(), 1);
}
use of org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl in project incubator-pulsar by apache.
the class ModularLoadManagerImplTest method testNeedBrokerDataUpdate.
// Test that ModularLoadManagerImpl will determine that writing local data to ZooKeeper is necessary if certain
// metrics change by a percentage threshold.
@Test
public void testNeedBrokerDataUpdate() throws Exception {
final LocalBrokerData lastData = new LocalBrokerData();
final LocalBrokerData currentData = new LocalBrokerData();
final ServiceConfiguration conf = pulsar1.getConfiguration();
// Set this manually in case the default changes.
conf.setLoadBalancerReportUpdateThresholdPercentage(5);
// Easier to test using an uninitialized ModularLoadManagerImpl.
final ModularLoadManagerImpl loadManager = new ModularLoadManagerImpl();
setField(loadManager, "lastData", lastData);
setField(loadManager, "localData", currentData);
setField(loadManager, "conf", conf);
Supplier<Boolean> needUpdate = () -> {
try {
return (Boolean) invokeSimpleMethod(loadManager, "needBrokerDataUpdate");
} catch (Exception e) {
throw new RuntimeException(e);
}
};
lastData.setMsgRateIn(100);
currentData.setMsgRateIn(104);
// 4% difference: shouldn't trigger an update.
assert (!needUpdate.get());
currentData.setMsgRateIn(105.1);
// 5% difference: should trigger an update (exactly 5% is flaky due to precision).
assert (needUpdate.get());
// Do similar tests for lower values.
currentData.setMsgRateIn(94);
assert (needUpdate.get());
currentData.setMsgRateIn(95.1);
assert (!needUpdate.get());
// 0 to non-zero should always trigger an update.
lastData.setMsgRateIn(0);
currentData.setMsgRateIn(1e-8);
assert (needUpdate.get());
// non-zero to zero should trigger an update as long as the threshold is less than 100.
lastData.setMsgRateIn(1e-8);
currentData.setMsgRateIn(0);
assert (needUpdate.get());
// zero to zero should never trigger an update.
currentData.setMsgRateIn(0);
lastData.setMsgRateIn(0);
assert (!needUpdate.get());
// Minimally test other absolute values to ensure they are included.
lastData.getCpu().usage = 100;
lastData.getCpu().limit = 1000;
currentData.getCpu().usage = 106;
currentData.getCpu().limit = 1000;
assert (!needUpdate.get());
// Minimally test other absolute values to ensure they are included.
lastData.getCpu().usage = 100;
lastData.getCpu().limit = 1000;
currentData.getCpu().usage = 206;
currentData.getCpu().limit = 1000;
assert (needUpdate.get());
lastData.setCpu(new ResourceUsage());
currentData.setCpu(new ResourceUsage());
lastData.setMsgThroughputIn(100);
currentData.setMsgThroughputIn(106);
assert (needUpdate.get());
currentData.setMsgThroughputIn(100);
lastData.setNumBundles(100);
currentData.setNumBundles(106);
assert (needUpdate.get());
currentData.setNumBundles(100);
assert (!needUpdate.get());
}
use of org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl in project incubator-pulsar by apache.
the class BrokerServiceLookupTest method testModularLoadManagerSplitBundle.
/**
* <pre>
* When broker-1's Modular-load-manager splits the bundle and update local-policies, broker-2 should get watch of
* local-policies and update bundleCache so, new lookup can be redirected properly.
*
* (1) Start broker-1 and broker-2
* (2) Make sure broker-2 always assign bundle to broker1
* (3) Broker-2 receives topic-1 request, creates local-policies and sets the watch
* (4) Broker-1 will own topic-1
* (5) Broker-2 will be a leader and trigger Split the bundle for topic-1
* (6) Broker-2 should get the watch and update bundle cache
* (7) Make lookup request again to Broker-2 which should succeed.
*
* </pre>
*
* @throws Exception
*/
@Test(timeOut = 5000)
public void testModularLoadManagerSplitBundle() throws Exception {
log.info("-- Starting {} test --", methodName);
final String loadBalancerName = conf.getLoadManagerClassName();
try {
final String namespace = "my-property/use/my-ns";
// (1) Start broker-1
ServiceConfiguration conf2 = new ServiceConfiguration();
conf2.setAdvertisedAddress("localhost");
conf2.setBrokerServicePort(PortManager.nextFreePort());
conf2.setBrokerServicePortTls(PortManager.nextFreePort());
conf2.setWebServicePort(PortManager.nextFreePort());
conf2.setWebServicePortTls(PortManager.nextFreePort());
conf2.setAdvertisedAddress("localhost");
conf2.setClusterName(conf.getClusterName());
conf2.setLoadManagerClassName(ModularLoadManagerImpl.class.getName());
conf2.setZookeeperServers("localhost:2181");
PulsarService pulsar2 = startBroker(conf2);
// configure broker-1 with ModularLoadlManager
stopBroker();
conf.setLoadManagerClassName(ModularLoadManagerImpl.class.getName());
startBroker();
pulsar.getLoadManager().get().writeLoadReportOnZookeeper();
pulsar2.getLoadManager().get().writeLoadReportOnZookeeper();
LoadManager loadManager1 = spy(pulsar.getLoadManager().get());
LoadManager loadManager2 = spy(pulsar2.getLoadManager().get());
Field loadManagerField = NamespaceService.class.getDeclaredField("loadManager");
loadManagerField.setAccessible(true);
// (2) Make sure broker-2 always assign bundle to broker1
// mock: redirect request to leader [2]
doReturn(true).when(loadManager2).isCentralized();
loadManagerField.set(pulsar2.getNamespaceService(), new AtomicReference<>(loadManager2));
// mock: return Broker1 as a Least-loaded broker when leader receies request [3]
doReturn(true).when(loadManager1).isCentralized();
SimpleResourceUnit resourceUnit = new SimpleResourceUnit(pulsar.getWebServiceAddress(), null);
Optional<ResourceUnit> res = Optional.of(resourceUnit);
doReturn(res).when(loadManager1).getLeastLoaded(any(ServiceUnitId.class));
loadManagerField.set(pulsar.getNamespaceService(), new AtomicReference<>(loadManager1));
URI broker2ServiceUrl = new URI("pulsar://localhost:" + conf2.getBrokerServicePort());
PulsarClient pulsarClient2 = PulsarClient.builder().serviceUrl(broker2ServiceUrl.toString()).build();
// (3) Broker-2 receives topic-1 request, creates local-policies and sets the watch
final String topic1 = "persistent://" + namespace + "/topic1";
Consumer<byte[]> consumer1 = pulsarClient2.newConsumer().topic(topic1).subscriptionName("my-subscriber-name").subscribe();
Set<String> serviceUnits1 = pulsar.getNamespaceService().getOwnedServiceUnits().stream().map(nb -> nb.toString()).collect(Collectors.toSet());
// (4) Broker-1 will own topic-1
final String unsplitBundle = namespace + "/0x00000000_0xffffffff";
assertTrue(serviceUnits1.contains(unsplitBundle));
// broker-2 should have this bundle into the cache
TopicName topicName = TopicName.get(topic1);
NamespaceBundle bundleInBroker2 = pulsar2.getNamespaceService().getBundle(topicName);
assertEquals(bundleInBroker2.toString(), unsplitBundle);
// update broker-1 bundle report to zk
pulsar.getBrokerService().updateRates();
pulsar.getLoadManager().get().writeLoadReportOnZookeeper();
// this will create znode for bundle-data
pulsar.getLoadManager().get().writeResourceQuotasToZooKeeper();
pulsar2.getLoadManager().get().writeLoadReportOnZookeeper();
// (5) Modular-load-manager will split the bundle due to max-topic threshold reached
Field leaderField = LeaderElectionService.class.getDeclaredField("isLeader");
Method updateAllMethod = ModularLoadManagerImpl.class.getDeclaredMethod("updateAll");
updateAllMethod.setAccessible(true);
leaderField.setAccessible(true);
AtomicBoolean isLeader = (AtomicBoolean) leaderField.get(pulsar2.getLeaderElectionService());
isLeader.set(true);
ModularLoadManagerImpl loadManager = (ModularLoadManagerImpl) ((ModularLoadManagerWrapper) pulsar2.getLoadManager().get()).getLoadManager();
// broker-2 loadManager is a leader and let it refresh load-report from all the brokers
updateAllMethod.invoke(loadManager);
conf2.setLoadBalancerAutoBundleSplitEnabled(true);
conf2.setLoadBalancerAutoUnloadSplitBundlesEnabled(true);
conf2.setLoadBalancerNamespaceBundleMaxTopics(0);
loadManager.checkNamespaceBundleSplit();
// (6) Broker-2 should get the watch and update bundle cache
final int retry = 5;
for (int i = 0; i < retry; i++) {
if (pulsar2.getNamespaceService().getBundle(topicName).equals(bundleInBroker2) && i != retry - 1) {
Thread.sleep(200);
} else {
break;
}
}
// (7) Make lookup request again to Broker-2 which should succeed.
final String topic2 = "persistent://" + namespace + "/topic2";
Consumer<byte[]> consumer2 = pulsarClient.newConsumer().topic(topic2).subscriptionName("my-subscriber-name").subscribe();
NamespaceBundle bundleInBroker1AfterSplit = pulsar2.getNamespaceService().getBundle(TopicName.get(topic2));
assertFalse(bundleInBroker1AfterSplit.equals(unsplitBundle));
consumer1.close();
consumer2.close();
pulsarClient2.close();
pulsar2.close();
} finally {
conf.setLoadManagerClassName(loadBalancerName);
}
}
use of org.apache.pulsar.broker.loadbalance.impl.ModularLoadManagerImpl in project incubator-pulsar by apache.
the class AntiAffinityNamespaceGroupTest method setup.
@BeforeMethod
void setup() throws Exception {
// Start local bookkeeper ensemble
bkEnsemble = new LocalBookkeeperEnsemble(3, ZOOKEEPER_PORT, PortManager.nextFreePort());
bkEnsemble.start();
// Start broker 1
ServiceConfiguration config1 = new ServiceConfiguration();
config1.setLoadManagerClassName(ModularLoadManagerImpl.class.getName());
config1.setClusterName("use");
config1.setWebServicePort(PRIMARY_BROKER_WEBSERVICE_PORT);
config1.setZookeeperServers("127.0.0.1" + ":" + ZOOKEEPER_PORT);
config1.setBrokerServicePort(PRIMARY_BROKER_PORT);
config1.setFailureDomainsEnabled(true);
config1.setLoadBalancerEnabled(true);
config1.setAdvertisedAddress("localhost");
createCluster(bkEnsemble.getZkClient(), config1);
pulsar1 = new PulsarService(config1);
pulsar1.start();
primaryHost = String.format("%s:%d", "localhost", PRIMARY_BROKER_WEBSERVICE_PORT);
url1 = new URL("http://127.0.0.1" + ":" + PRIMARY_BROKER_WEBSERVICE_PORT);
admin1 = new PulsarAdmin(url1, (Authentication) null);
// Start broker 2
ServiceConfiguration config2 = new ServiceConfiguration();
config2.setLoadManagerClassName(ModularLoadManagerImpl.class.getName());
config2.setClusterName("use");
config2.setWebServicePort(SECONDARY_BROKER_WEBSERVICE_PORT);
config2.setZookeeperServers("127.0.0.1" + ":" + ZOOKEEPER_PORT);
config2.setBrokerServicePort(SECONDARY_BROKER_PORT);
config2.setFailureDomainsEnabled(true);
pulsar2 = new PulsarService(config2);
secondaryHost = String.format("%s:%d", "localhost", SECONDARY_BROKER_WEBSERVICE_PORT);
pulsar2.start();
url2 = new URL("http://127.0.0.1" + ":" + SECONDARY_BROKER_WEBSERVICE_PORT);
admin2 = new PulsarAdmin(url2, (Authentication) null);
primaryLoadManager = (ModularLoadManagerImpl) getField(pulsar1.getLoadManager().get(), "loadManager");
secondaryLoadManager = (ModularLoadManagerImpl) getField(pulsar2.getLoadManager().get(), "loadManager");
nsFactory = new NamespaceBundleFactory(pulsar1, Hashing.crc32());
Thread.sleep(100);
}
Aggregations