You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by fj...@apache.org on 2019/03/12 14:09:19 UTC

[incubator-druid] branch master updated: lifecycle stage refactor to ensure proper start and stop ordering of servers and announcements (#7234)

This is an automated email from the ASF dual-hosted git repository.

fjy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 4d3987c  lifecycle stage refactor to ensure proper start and stop ordering of servers and announcements (#7234)
4d3987c is described below

commit 4d3987c1ddf1a4089bf02af9d43b3c918ce63560
Author: Clint Wylie <cj...@gmail.com>
AuthorDate: Tue Mar 12 07:09:03 2019 -0700

    lifecycle stage refactor to ensure proper start and stop ordering of servers and announcements (#7234)
    
    * lifecycle stage refactor to ensure proper ordering of servers and announcements
    
    * move DerivativeDataSourceManager to Lifecycle.Stage.NORMAL
---
 .../org/apache/druid/guice/LifecycleModule.java    |  9 ++++--
 ...Last.java => ManageLifecycleAnnouncements.java} |  4 +--
 ...fecycleLast.java => ManageLifecycleServer.java} |  6 ++--
 .../java/util/common/lifecycle/Lifecycle.java      | 32 +++++++++++++++------
 .../java/util/common/lifecycle/LifecycleTest.java  | 33 ++++++++++++++--------
 .../DerivativeDataSourceManager.java               |  4 +--
 .../druid/curator/announcement/Announcer.java      |  4 +--
 .../druid/curator/discovery/DiscoveryModule.java   | 10 +++----
 .../org/apache/druid/guice/AnnouncerModule.java    |  2 +-
 .../CuratorDataSegmentServerAnnouncer.java         |  2 +-
 .../initialization/jetty/JettyServerModule.java    |  2 +-
 .../java/org/apache/druid/cli/ServerRunnable.java  |  4 +--
 12 files changed, 70 insertions(+), 42 deletions(-)

diff --git a/core/src/main/java/org/apache/druid/guice/LifecycleModule.java b/core/src/main/java/org/apache/druid/guice/LifecycleModule.java
index bbe5ccf..b2ec09b 100644
--- a/core/src/main/java/org/apache/druid/guice/LifecycleModule.java
+++ b/core/src/main/java/org/apache/druid/guice/LifecycleModule.java
@@ -41,7 +41,8 @@ public class LifecycleModule implements Module
   // the 'stop' method, either failing silently or failing violently and throwing an exception causing an ungraceful exit
   private final LifecycleScope initScope = new LifecycleScope(Lifecycle.Stage.INIT);
   private final LifecycleScope scope = new LifecycleScope(Lifecycle.Stage.NORMAL);
-  private final LifecycleScope lastScope = new LifecycleScope(Lifecycle.Stage.LAST);
+  private final LifecycleScope serverScope = new LifecycleScope(Lifecycle.Stage.SERVER);
+  private final LifecycleScope annoucementsScope = new LifecycleScope(Lifecycle.Stage.ANNOUNCEMENTS);
 
   /**
    * Registers a class to instantiate eagerly.  Classes mentioned here will be pulled out of
@@ -118,7 +119,8 @@ public class LifecycleModule implements Module
 
     binder.bindScope(ManageLifecycleInit.class, initScope);
     binder.bindScope(ManageLifecycle.class, scope);
-    binder.bindScope(ManageLifecycleLast.class, lastScope);
+    binder.bindScope(ManageLifecycleServer.class, serverScope);
+    binder.bindScope(ManageLifecycleAnnouncements.class, annoucementsScope);
   }
 
   @Provides @LazySingleton
@@ -140,7 +142,8 @@ public class LifecycleModule implements Module
     };
     initScope.setLifecycle(lifecycle);
     scope.setLifecycle(lifecycle);
-    lastScope.setLifecycle(lifecycle);
+    serverScope.setLifecycle(lifecycle);
+    annoucementsScope.setLifecycle(lifecycle);
 
     return lifecycle;
   }
diff --git a/core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java b/core/src/main/java/org/apache/druid/guice/ManageLifecycleAnnouncements.java
similarity index 91%
copy from core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java
copy to core/src/main/java/org/apache/druid/guice/ManageLifecycleAnnouncements.java
index e893719..f9537bc 100644
--- a/core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java
+++ b/core/src/main/java/org/apache/druid/guice/ManageLifecycleAnnouncements.java
@@ -28,7 +28,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * Marks the object to be managed by {@link org.apache.druid.java.util.common.lifecycle.Lifecycle} and set to be on Stage.LAST
+ * Marks the object to be managed by {@link org.apache.druid.java.util.common.lifecycle.Lifecycle} and set to be on Stage.ANNOUNCEMENTS
  *
  * This Scope gets defined by {@link LifecycleModule}
  */
@@ -36,6 +36,6 @@ import java.lang.annotation.Target;
 @Retention(RetentionPolicy.RUNTIME)
 @ScopeAnnotation
 @PublicApi
-public @interface ManageLifecycleLast
+public @interface ManageLifecycleAnnouncements
 {
 }
diff --git a/core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java b/core/src/main/java/org/apache/druid/guice/ManageLifecycleServer.java
similarity index 89%
rename from core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java
rename to core/src/main/java/org/apache/druid/guice/ManageLifecycleServer.java
index e893719..f17b49a 100644
--- a/core/src/main/java/org/apache/druid/guice/ManageLifecycleLast.java
+++ b/core/src/main/java/org/apache/druid/guice/ManageLifecycleServer.java
@@ -28,14 +28,14 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * Marks the object to be managed by {@link org.apache.druid.java.util.common.lifecycle.Lifecycle} and set to be on Stage.LAST
+ * Marks the object to be managed by {@link org.apache.druid.java.util.common.lifecycle.Lifecycle} and set to be on Stage.SERVER
  *
  * This Scope gets defined by {@link LifecycleModule}
  */
-@Target({ ElementType.TYPE, ElementType.METHOD })
+@Target({ElementType.TYPE, ElementType.METHOD })
 @Retention(RetentionPolicy.RUNTIME)
 @ScopeAnnotation
 @PublicApi
-public @interface ManageLifecycleLast
+public @interface ManageLifecycleServer
 {
 }
diff --git a/core/src/main/java/org/apache/druid/java/util/common/lifecycle/Lifecycle.java b/core/src/main/java/org/apache/druid/java/util/common/lifecycle/Lifecycle.java
index d26736c..b9e5b41 100644
--- a/core/src/main/java/org/apache/druid/java/util/common/lifecycle/Lifecycle.java
+++ b/core/src/main/java/org/apache/druid/java/util/common/lifecycle/Lifecycle.java
@@ -40,15 +40,30 @@ import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * A manager of object Lifecycles.
- * <p/>
+ *
  * This object has methods for registering objects that should be started and stopped.  The Lifecycle allows for
- * three stages: Stage.INIT, Stage.NORMAL, and Stage.LAST.
- * <p/>
+ * four stages: Stage.INIT, Stage.NORMAL, Stage.SERVER, and Stage.ANNOUNCEMENTS.
+ *
  * Things added at Stage.INIT will be started first (in the order that they are added to the Lifecycle instance) and
- * then things added at Stage.NORMAL, and finally, Stage.LAST will be started.
- * <p/>
- * The close operation goes in reverse order, starting with the last thing added at Stage.LAST and working backwards.
- * <p/>
+ * then things added at Stage.NORMAL, then Stage.SERVER, and finally, Stage.ANNOUNCEMENTS will be started.
+ *
+ * The close operation goes in reverse order, starting with the last thing added at Stage.ANNOUNCEMENTS and working
+ * backwards.
+ *
+ * Conceptually, the stages have the following purposes:
+ *  - Stage.INIT: Currently, this stage is used exclusively for log4j initialization, since almost everything needs
+ *    logging and it should be the last thing to shutdown. Any sort of bootstrapping object that provides something that
+ *    should be initialized before nearly all other Lifecycle objects could also belong here (if it doesn't need
+ *    logging during start or stop).
+ *  - Stage.NORMAL: This is the default stage. Most objects will probably make the most sense to be registered at
+ *    this level, with the exception of any form of server or service announcements
+ *  - Stage.SERVER: This lifecycle stage is intended for all 'server' objects, and currently only contains the Jetty
+ *    module, but any sort of 'server' that expects most Lifecycle objects to be initialized by the time it starts, and
+ *    still available at the time it stops can logically live in this stage.
+ *  - Stage.ANNOUNCENTS: Any object which announces to a cluster this servers location belongs in this stage. By being
+ *    last, we can be sure that all servers are initialized before we advertise the endpoint locations, and also can be
+ *    sure that we un-announce these advertisements prior to the Stage.SERVER objects stop.
+ *
  * There are two sets of methods to add things to the Lifecycle.  One set that will just add instances and enforce that
  * start() has not been called yet.  The other set will add instances and, if the lifecycle is already started, start
  * them.
@@ -61,7 +76,8 @@ public class Lifecycle
   {
     INIT,
     NORMAL,
-    LAST
+    SERVER,
+    ANNOUNCEMENTS
   }
 
   private enum State
diff --git a/core/src/test/java/org/apache/druid/java/util/common/lifecycle/LifecycleTest.java b/core/src/test/java/org/apache/druid/java/util/common/lifecycle/LifecycleTest.java
index 6354cdd..26b19af 100644
--- a/core/src/test/java/org/apache/druid/java/util/common/lifecycle/LifecycleTest.java
+++ b/core/src/test/java/org/apache/druid/java/util/common/lifecycle/LifecycleTest.java
@@ -172,25 +172,26 @@ public class LifecycleTest
     lifecycle.addManagedInstance(new ObjectToBeLifecycled(0, startOrder, stopOrder));
     lifecycle.addManagedInstance(new ObjectToBeLifecycled(1, startOrder, stopOrder), Lifecycle.Stage.NORMAL);
     lifecycle.addManagedInstance(new ObjectToBeLifecycled(2, startOrder, stopOrder), Lifecycle.Stage.NORMAL);
-    lifecycle.addManagedInstance(new ObjectToBeLifecycled(3, startOrder, stopOrder), Lifecycle.Stage.LAST);
+    lifecycle.addManagedInstance(new ObjectToBeLifecycled(3, startOrder, stopOrder), Lifecycle.Stage.ANNOUNCEMENTS);
     lifecycle.addStartCloseInstance(new ObjectToBeLifecycled(4, startOrder, stopOrder));
     lifecycle.addManagedInstance(new ObjectToBeLifecycled(5, startOrder, stopOrder));
-    lifecycle.addStartCloseInstance(new ObjectToBeLifecycled(6, startOrder, stopOrder), Lifecycle.Stage.LAST);
+    lifecycle.addStartCloseInstance(new ObjectToBeLifecycled(6, startOrder, stopOrder), Lifecycle.Stage.ANNOUNCEMENTS);
     lifecycle.addManagedInstance(new ObjectToBeLifecycled(7, startOrder, stopOrder));
     lifecycle.addStartCloseInstance(new ObjectToBeLifecycled(8, startOrder, stopOrder), Lifecycle.Stage.INIT);
+    lifecycle.addStartCloseInstance(new ObjectToBeLifecycled(9, startOrder, stopOrder), Lifecycle.Stage.SERVER);
 
-    final List<Integer> expectedOrder = Arrays.asList(8, 0, 1, 2, 4, 5, 7, 3, 6);
+    final List<Integer> expectedOrder = Arrays.asList(8, 0, 1, 2, 4, 5, 7, 9, 3, 6);
 
     lifecycle.start();
 
-    Assert.assertEquals(9, startOrder.size());
+    Assert.assertEquals(10, startOrder.size());
     Assert.assertEquals(0, stopOrder.size());
     Assert.assertEquals(expectedOrder, startOrder);
 
     lifecycle.stop();
 
-    Assert.assertEquals(9, startOrder.size());
-    Assert.assertEquals(9, stopOrder.size());
+    Assert.assertEquals(10, startOrder.size());
+    Assert.assertEquals(10, stopOrder.size());
     Assert.assertEquals(Lists.reverse(expectedOrder), stopOrder);
   }
 
@@ -210,20 +211,28 @@ public class LifecycleTest
           public void start() throws Exception
           {
             lifecycle.addMaybeStartManagedInstance(
-                new ObjectToBeLifecycled(1, startOrder, stopOrder), Lifecycle.Stage.NORMAL
+                new ObjectToBeLifecycled(1, startOrder, stopOrder),
+                Lifecycle.Stage.NORMAL
             );
             lifecycle.addMaybeStartManagedInstance(
-                new ObjectToBeLifecycled(2, startOrder, stopOrder), Lifecycle.Stage.INIT
+                new ObjectToBeLifecycled(2, startOrder, stopOrder),
+                Lifecycle.Stage.INIT
             );
             lifecycle.addMaybeStartManagedInstance(
-                new ObjectToBeLifecycled(3, startOrder, stopOrder), Lifecycle.Stage.LAST
+                new ObjectToBeLifecycled(3, startOrder, stopOrder),
+                Lifecycle.Stage.ANNOUNCEMENTS
             );
             lifecycle.addMaybeStartStartCloseInstance(new ObjectToBeLifecycled(4, startOrder, stopOrder));
             lifecycle.addMaybeStartManagedInstance(new ObjectToBeLifecycled(5, startOrder, stopOrder));
             lifecycle.addMaybeStartStartCloseInstance(
-                new ObjectToBeLifecycled(6, startOrder, stopOrder), Lifecycle.Stage.LAST
+                new ObjectToBeLifecycled(6, startOrder, stopOrder),
+                Lifecycle.Stage.ANNOUNCEMENTS
             );
             lifecycle.addMaybeStartManagedInstance(new ObjectToBeLifecycled(7, startOrder, stopOrder));
+            lifecycle.addMaybeStartManagedInstance(
+                new ObjectToBeLifecycled(8, startOrder, stopOrder),
+                Lifecycle.Stage.SERVER
+            );
           }
 
           @Override
@@ -234,8 +243,8 @@ public class LifecycleTest
         }
     );
 
-    final List<Integer> expectedOrder = Arrays.asList(0, 1, 2, 4, 5, 7, 3, 6);
-    final List<Integer> expectedStopOrder = Arrays.asList(6, 3, 7, 5, 4, 1, 0, 2);
+    final List<Integer> expectedOrder = Arrays.asList(0, 1, 2, 4, 5, 7, 8, 3, 6);
+    final List<Integer> expectedStopOrder = Arrays.asList(6, 3, 8, 7, 5, 4, 1, 0, 2);
 
     lifecycle.start();
 
diff --git a/extensions-contrib/materialized-view-selection/src/main/java/org/apache/druid/query/materializedview/DerivativeDataSourceManager.java b/extensions-contrib/materialized-view-selection/src/main/java/org/apache/druid/query/materializedview/DerivativeDataSourceManager.java
index 35a5c28..345f4bf 100644
--- a/extensions-contrib/materialized-view-selection/src/main/java/org/apache/druid/query/materializedview/DerivativeDataSourceManager.java
+++ b/extensions-contrib/materialized-view-selection/src/main/java/org/apache/druid/query/materializedview/DerivativeDataSourceManager.java
@@ -27,7 +27,7 @@ import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningScheduledExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.inject.Inject;
-import org.apache.druid.guice.ManageLifecycleLast;
+import org.apache.druid.guice.ManageLifecycle;
 import org.apache.druid.indexing.materializedview.DerivativeDataSourceMetadata;
 import org.apache.druid.indexing.overlord.DataSourceMetadata;
 import org.apache.druid.java.util.common.DateTimes;
@@ -65,7 +65,7 @@ import java.util.stream.Collectors;
  * Read and store derivatives information from dataSource table frequently.
  * When optimize query, DerivativesManager offers the information about derivatives.
  */
-@ManageLifecycleLast
+@ManageLifecycle
 public class DerivativeDataSourceManager 
 {
   private static final EmittingLogger log = new EmittingLogger(DerivativeDataSourceManager.class);
diff --git a/server/src/main/java/org/apache/druid/curator/announcement/Announcer.java b/server/src/main/java/org/apache/druid/curator/announcement/Announcer.java
index 50193db..c3cb7da 100644
--- a/server/src/main/java/org/apache/druid/curator/announcement/Announcer.java
+++ b/server/src/main/java/org/apache/druid/curator/announcement/Announcer.java
@@ -387,16 +387,16 @@ public class Announcer
    */
   public void unannounce(String path)
   {
-    log.info("unannouncing [%s]", path);
     final ZKPaths.PathAndNode pathAndNode = ZKPaths.getPathAndNode(path);
     final String parentPath = pathAndNode.getPath();
 
     final ConcurrentMap<String, byte[]> subPaths = announcements.get(parentPath);
 
     if (subPaths == null || subPaths.remove(pathAndNode.getNode()) == null) {
-      log.error("Path[%s] not announced, cannot unannounce.", path);
+      log.debug("Path[%s] not announced, cannot unannounce.", path);
       return;
     }
+    log.info("unannouncing [%s]", path);
 
     try {
       curator.inTransaction().delete().forPath(path).and().commit();
diff --git a/server/src/main/java/org/apache/druid/curator/discovery/DiscoveryModule.java b/server/src/main/java/org/apache/druid/curator/discovery/DiscoveryModule.java
index 0548203..d38601c 100644
--- a/server/src/main/java/org/apache/druid/curator/discovery/DiscoveryModule.java
+++ b/server/src/main/java/org/apache/druid/curator/discovery/DiscoveryModule.java
@@ -92,7 +92,7 @@ public class DiscoveryModule implements Module
    * 
    * That is, this module will announce the DruidNode instance returned by
    * injector.getInstance(Key.get(DruidNode.class)) automatically.
-   * Announcement will happen in the LAST stage of the Lifecycle
+   * Announcement will happen in the ANNOUNCEMENTS stage of the Lifecycle
    *
    * @param binder the Binder to register with
    */
@@ -106,7 +106,7 @@ public class DiscoveryModule implements Module
    * 
    * That is, this module will announce the DruidNode instance returned by
    * injector.getInstance(Key.get(DruidNode.class, annotation)) automatically.
-   * Announcement will happen in the LAST stage of the Lifecycle
+   * Announcement will happen in the ANNOUNCEMENTS stage of the Lifecycle
    *
    * @param annotation The annotation instance to use in finding the DruidNode instance, usually a Named annotation
    */
@@ -120,7 +120,7 @@ public class DiscoveryModule implements Module
    * 
    * That is, this module will announce the DruidNode instance returned by
    * injector.getInstance(Key.get(DruidNode.class, annotation)) automatically.
-   * Announcement will happen in the LAST stage of the Lifecycle
+   * Announcement will happen in the ANNOUNCEMENTS stage of the Lifecycle
    *
    * @param binder the Binder to register with
    * @param annotation The annotation class to use in finding the DruidNode instance
@@ -135,7 +135,7 @@ public class DiscoveryModule implements Module
    * 
    * That is, this module will announce the DruidNode instance returned by
    * injector.getInstance(Key.get(DruidNode.class, annotation)) automatically.
-   * Announcement will happen in the LAST stage of the Lifecycle
+   * Announcement will happen in the ANNOUNCEMENTS stage of the Lifecycle
    *
    * @param binder the Binder to register with
    * @param key The key to use in finding the DruidNode instance
@@ -251,7 +251,7 @@ public class DiscoveryModule implements Module
             }
           }
         },
-        Lifecycle.Stage.LAST
+        Lifecycle.Stage.ANNOUNCEMENTS
     );
 
     return announcer;
diff --git a/server/src/main/java/org/apache/druid/guice/AnnouncerModule.java b/server/src/main/java/org/apache/druid/guice/AnnouncerModule.java
index bb58e69..3a48183 100644
--- a/server/src/main/java/org/apache/druid/guice/AnnouncerModule.java
+++ b/server/src/main/java/org/apache/druid/guice/AnnouncerModule.java
@@ -47,7 +47,7 @@ public class AnnouncerModule implements Module
   }
 
   @Provides
-  @ManageLifecycle
+  @ManageLifecycleAnnouncements
   public Announcer getAnnouncer(CuratorFramework curator)
   {
     return new Announcer(curator, Execs.singleThreaded("Announcer-%s"));
diff --git a/server/src/main/java/org/apache/druid/server/coordination/CuratorDataSegmentServerAnnouncer.java b/server/src/main/java/org/apache/druid/server/coordination/CuratorDataSegmentServerAnnouncer.java
index 909f0c3..5954100 100644
--- a/server/src/main/java/org/apache/druid/server/coordination/CuratorDataSegmentServerAnnouncer.java
+++ b/server/src/main/java/org/apache/druid/server/coordination/CuratorDataSegmentServerAnnouncer.java
@@ -89,7 +89,7 @@ public class CuratorDataSegmentServerAnnouncer implements DataSegmentServerAnnou
       }
 
       final String path = makeAnnouncementPath();
-      log.info("Unannouncing self[%s] at [%s]", server, path);
+      log.debug("Unannouncing self[%s] at [%s]", server, path);
       announcer.unannounce(path);
 
       announced = false;
diff --git a/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java b/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
index 0454f8d..8966231 100644
--- a/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
+++ b/server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java
@@ -441,7 +441,7 @@ public class JettyServerModule extends JerseyServletModule
             }
           }
         },
-        Lifecycle.Stage.LAST
+        Lifecycle.Stage.SERVER
     );
 
     return server;
diff --git a/services/src/main/java/org/apache/druid/cli/ServerRunnable.java b/services/src/main/java/org/apache/druid/cli/ServerRunnable.java
index 77d409c..8429a05 100644
--- a/services/src/main/java/org/apache/druid/cli/ServerRunnable.java
+++ b/services/src/main/java/org/apache/druid/cli/ServerRunnable.java
@@ -93,7 +93,7 @@ public abstract class ServerRunnable extends GuiceRunnable
 
   /**
    * This is a helper class used by CliXXX classes to announce {@link DiscoveryDruidNode}
-   * as part of {@link Lifecycle.Stage#LAST}.
+   * as part of {@link Lifecycle.Stage#ANNOUNCEMENTS}.
    */
   protected static class DiscoverySideEffectsProvider implements Provider<DiscoverySideEffectsProvider.Child>
   {
@@ -200,7 +200,7 @@ public abstract class ServerRunnable extends GuiceRunnable
               announcer.unannounce(discoveryDruidNode);
             }
           },
-          Lifecycle.Stage.LAST
+          Lifecycle.Stage.ANNOUNCEMENTS
       );
 
       return new Child();


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org