8181import org .apache .pulsar .broker .loadbalance .extensions .scheduler .SplitScheduler ;
8282import org .apache .pulsar .broker .loadbalance .extensions .scheduler .UnloadScheduler ;
8383import org .apache .pulsar .broker .loadbalance .extensions .store .LoadDataStore ;
84- import org .apache .pulsar .broker .loadbalance .extensions .store .LoadDataStoreException ;
8584import org .apache .pulsar .broker .loadbalance .extensions .store .LoadDataStoreFactory ;
8685import org .apache .pulsar .broker .loadbalance .extensions .strategy .BrokerSelectionStrategy ;
8786import org .apache .pulsar .broker .loadbalance .extensions .strategy .BrokerSelectionStrategyFactory ;
9998import org .apache .pulsar .common .naming .TopicDomain ;
10099import org .apache .pulsar .common .naming .TopicName ;
101100import org .apache .pulsar .common .stats .Metrics ;
102- import org .apache .pulsar .common .util .Backoff ;
103- import org .apache .pulsar .common .util .BackoffBuilder ;
104101import org .apache .pulsar .common .util .FutureUtil ;
105- import org .apache .pulsar .metadata .api .MetadataStoreException ;
106102import org .apache .pulsar .metadata .api .coordination .LeaderElectionState ;
107103import org .slf4j .Logger ;
108104
@@ -125,10 +121,6 @@ public class ExtensibleLoadManagerImpl implements ExtensibleLoadManager, BrokerS
125121
126122 public static final long COMPACTION_THRESHOLD = 5 * 1024 * 1024 ;
127123
128- public static final int STARTUP_TIMEOUT_SECONDS = 30 ;
129-
130- public static final int MAX_RETRY = 5 ;
131-
132124 private static final String ELECTION_ROOT = "/loadbalance/extension/leader" ;
133125
134126 public static final Set <String > INTERNAL_TOPICS =
@@ -212,7 +204,7 @@ public class ExtensibleLoadManagerImpl implements ExtensibleLoadManager, BrokerS
212204
213205 private final ConcurrentHashMap <String , CompletableFuture <Optional <BrokerLookupData >>>
214206 lookupRequests = new ConcurrentHashMap <>();
215- private final CompletableFuture <Void > initWaiter = new CompletableFuture <>();
207+ private final CompletableFuture <Boolean > initWaiter = new CompletableFuture <>();
216208
217209 /**
218210 * Get all the bundles that are owned by this broker.
@@ -385,7 +377,7 @@ public void start() throws PulsarServerException {
385377 return ;
386378 }
387379 try {
388- this .brokerRegistry = new BrokerRegistryImpl (pulsar );
380+ this .brokerRegistry = createBrokerRegistry (pulsar );
389381 this .leaderElectionService = new LeaderElectionService (
390382 pulsar .getCoordinationService (), pulsar .getBrokerId (),
391383 pulsar .getSafeWebServiceAddress (), ELECTION_ROOT ,
@@ -400,53 +392,14 @@ public void start() throws PulsarServerException {
400392 });
401393 });
402394 });
403- this .serviceUnitStateChannel = new ServiceUnitStateChannelImpl (pulsar );
395+ this .serviceUnitStateChannel = createServiceUnitStateChannel (pulsar );
404396 this .brokerRegistry .start ();
405397 this .splitManager = new SplitManager (splitCounter );
406398 this .unloadManager = new UnloadManager (unloadCounter , pulsar .getBrokerId ());
407399 this .serviceUnitStateChannel .listen (unloadManager );
408400 this .serviceUnitStateChannel .listen (splitManager );
409401 this .leaderElectionService .start ();
410- pulsar .runWhenReadyForIncomingRequests (() -> {
411- Backoff backoff = new BackoffBuilder ()
412- .setInitialTime (100 , TimeUnit .MILLISECONDS )
413- .setMax (STARTUP_TIMEOUT_SECONDS , TimeUnit .SECONDS )
414- .create ();
415- int retry = 0 ;
416- while (!Thread .currentThread ().isInterrupted ()) {
417- try {
418- brokerRegistry .register ();
419- this .serviceUnitStateChannel .start ();
420- break ;
421- } catch (Exception e ) {
422- log .warn ("The broker:{} failed to start service unit state channel. Retrying {} th ..." ,
423- pulsar .getBrokerId (), ++retry , e );
424- try {
425- Thread .sleep (backoff .next ());
426- } catch (InterruptedException ex ) {
427- log .warn ("Interrupted while sleeping." );
428- // preserve thread's interrupt status
429- Thread .currentThread ().interrupt ();
430- try {
431- pulsar .close ();
432- } catch (PulsarServerException exc ) {
433- log .error ("Failed to close pulsar service." , exc );
434- }
435- return ;
436- }
437- failStarting (e );
438- if (retry >= MAX_RETRY ) {
439- log .error ("Failed to start the service unit state channel after retry {} th. "
440- + "Closing pulsar service." , retry , e );
441- try {
442- pulsar .close ();
443- } catch (PulsarServerException ex ) {
444- log .error ("Failed to close pulsar service." , ex );
445- }
446- }
447- }
448- }
449- });
402+
450403 this .antiAffinityGroupPolicyHelper =
451404 new AntiAffinityGroupPolicyHelper (pulsar , serviceUnitStateChannel );
452405 antiAffinityGroupPolicyHelper .listenFailureDomainUpdate ();
@@ -455,15 +408,10 @@ public void start() throws PulsarServerException {
455408 SimpleResourceAllocationPolicies policies = new SimpleResourceAllocationPolicies (pulsar );
456409 this .isolationPoliciesHelper = new IsolationPoliciesHelper (policies );
457410 this .brokerFilterPipeline .add (new BrokerIsolationPoliciesFilter (isolationPoliciesHelper ));
458-
459- try {
460- this .brokerLoadDataStore = LoadDataStoreFactory
461- .create (pulsar , BROKER_LOAD_DATA_STORE_TOPIC , BrokerLoadData .class );
462- this .topBundlesLoadDataStore = LoadDataStoreFactory
463- .create (pulsar , TOP_BUNDLES_LOAD_DATA_STORE_TOPIC , TopBundlesLoadData .class );
464- } catch (LoadDataStoreException e ) {
465- throw new PulsarServerException (e );
466- }
411+ this .brokerLoadDataStore = LoadDataStoreFactory
412+ .create (pulsar , BROKER_LOAD_DATA_STORE_TOPIC , BrokerLoadData .class );
413+ this .topBundlesLoadDataStore = LoadDataStoreFactory
414+ .create (pulsar , TOP_BUNDLES_LOAD_DATA_STORE_TOPIC , TopBundlesLoadData .class );
467415
468416 this .context = LoadManagerContextImpl .builder ()
469417 .configuration (conf )
@@ -487,6 +435,7 @@ public void start() throws PulsarServerException {
487435
488436 pulsar .runWhenReadyForIncomingRequests (() -> {
489437 try {
438+ this .serviceUnitStateChannel .start ();
490439 var interval = conf .getLoadBalancerReportUpdateMinIntervalMillis ();
491440
492441 this .brokerLoadDataReportTask = this .pulsar .getLoadManagerExecutor ()
@@ -521,38 +470,33 @@ public void start() throws PulsarServerException {
521470 MONITOR_INTERVAL_IN_MILLIS , TimeUnit .MILLISECONDS );
522471
523472 this .splitScheduler .start ();
524- this .initWaiter .complete (null );
473+ this .initWaiter .complete (true );
525474 this .started = true ;
526475 log .info ("Started load manager." );
527- } catch (Exception ex ) {
528- failStarting (ex );
476+ } catch (Throwable e ) {
477+ failStarting (e );
529478 }
530479 });
531- } catch (Exception ex ) {
480+ } catch (Throwable ex ) {
532481 failStarting (ex );
533482 }
534483 }
535484
536- private void failStarting (Exception ex ) {
537- log .error ("Failed to start the extensible load balance and close broker registry {}." ,
538- this .brokerRegistry , ex );
485+ private void failStarting (Throwable throwable ) {
539486 if (this .brokerRegistry != null ) {
540487 try {
541- brokerRegistry .unregister ();
542- } catch (MetadataStoreException e ) {
543- // ignore
544- }
545- }
546- if (this .serviceUnitStateChannel != null ) {
547- try {
548- serviceUnitStateChannel .close ();
549- } catch (IOException e ) {
550- // ignore
488+ brokerRegistry .close ();
489+ } catch (PulsarServerException e ) {
490+ // If close failed, this broker might still exist in the metadata store. Then it could be found by other
491+ // brokers as an available broker. Hence, print a warning log for it.
492+ log .warn ("Failed to close the broker registry: {}" , e .getMessage ());
551493 }
552494 }
553- initWaiter .completeExceptionally (ex );
495+ initWaiter .complete (false ); // exit the background thread gracefully
496+ throw PulsarServerException .toUncheckedException (PulsarServerException .from (throwable ));
554497 }
555498
499+
556500 @ Override
557501 public void initialize (PulsarService pulsar ) {
558502 this .pulsar = pulsar ;
@@ -897,7 +841,9 @@ synchronized void playLeader() {
897841 boolean becameFollower = false ;
898842 while (!Thread .currentThread ().isInterrupted ()) {
899843 try {
900- initWaiter .get ();
844+ if (!initWaiter .get ()) {
845+ return ;
846+ }
901847 if (!serviceUnitStateChannel .isChannelOwner ()) {
902848 becameFollower = true ;
903849 break ;
@@ -947,7 +893,9 @@ synchronized void playFollower() {
947893 boolean becameLeader = false ;
948894 while (!Thread .currentThread ().isInterrupted ()) {
949895 try {
950- initWaiter .get ();
896+ if (!initWaiter .get ()) {
897+ return ;
898+ }
951899 if (serviceUnitStateChannel .isChannelOwner ()) {
952900 becameLeader = true ;
953901 break ;
@@ -1018,7 +966,9 @@ private List<Metrics> getIgnoredCommandMetrics(String advertisedBrokerAddress) {
1018966 @ VisibleForTesting
1019967 protected void monitor () {
1020968 try {
1021- initWaiter .get ();
969+ if (!initWaiter .get ()) {
970+ return ;
971+ }
1022972
1023973 // Monitor role
1024974 // Periodically check the role in case ZK watcher fails.
@@ -1073,4 +1023,14 @@ private void closeInternalTopics() {
10731023 log .warn ("Failed to wait for closing internal topics" , e );
10741024 }
10751025 }
1026+
1027+ @ VisibleForTesting
1028+ protected BrokerRegistry createBrokerRegistry (PulsarService pulsar ) {
1029+ return new BrokerRegistryImpl (pulsar );
1030+ }
1031+
1032+ @ VisibleForTesting
1033+ protected ServiceUnitStateChannel createServiceUnitStateChannel (PulsarService pulsar ) {
1034+ return new ServiceUnitStateChannelImpl (pulsar );
1035+ }
10761036}
0 commit comments