Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/operations/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ An endpoint that always returns a boolean "true" value with a 200 OK response, u

Returns the current configuration properties of the process.

* `/status/selfDiscoveredStatus`
* `/status/selfDiscovered/status`

Returns a JSON map of the form `{"selfDiscovered": true/false}`, indicating whether the node has received a confirmation
from the central node discovery mechanism (currently ZooKeeper) of the Druid cluster that the node has been added to the
Expand All @@ -60,7 +60,7 @@ nodes will be discovered by this node timely from this point.

* `/status/selfDiscovered`

Similar to `/status/selfDiscoveredStatus`, but returns 200 OK response with empty body if the node has discovered itself
Similar to `/status/selfDiscovered/status`, but returns 200 OK response with empty body if the node has discovered itself
and 503 SERVICE UNAVAILABLE if the node hasn't discovered itself yet. This endpoint might be useful because some
monitoring checks such as AWS load balancer health checks are not able to look at the response body.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package org.apache.druid.server.http;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.sun.jersey.spi.container.ResourceFilters;
Expand All @@ -36,6 +37,8 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.BooleanSupplier;

/**
Expand All @@ -44,58 +47,68 @@
* DI configuration phase.
*/
@Singleton
@Path("/status/selfDiscovered")
public class SelfDiscoveryResource
{
private BooleanSupplier selfDiscovered;
private final List<BooleanSupplier> selfDiscoveredRoles;

@Inject
public SelfDiscoveryResource(
@Self DruidNode thisDruidNode,
@Self NodeRole thisNodeRole,
@Self Set<NodeRole> thisNodeRoles,
DruidNodeDiscoveryProvider nodeDiscoveryProvider,
Lifecycle lifecycle
)
{
Lifecycle.Handler selfDiscoveryListenerRegistrator = new Lifecycle.Handler()
{
@Override
public void start()
{
selfDiscovered = nodeDiscoveryProvider.getForNode(thisDruidNode, thisNodeRole);
}
selfDiscoveredRoles = Lists.newArrayListWithExpectedSize(thisNodeRoles.size());
thisNodeRoles.forEach(
thisNodeRole -> {
Lifecycle.Handler selfDiscoveryListenerRegistrator = new Lifecycle.Handler()
{
@Override
public void start()
{
selfDiscoveredRoles.add(nodeDiscoveryProvider.getForNode(thisDruidNode, thisNodeRole));
}

@Override
public void stop()
{
// do nothing
}
};
// Using Lifecycle.Stage.SERVER because DruidNodeDiscoveryProvider should be already started when
// selfDiscoveryListenerRegistrator.start() is called.
lifecycle.addHandler(selfDiscoveryListenerRegistrator, Lifecycle.Stage.SERVER);
@Override
public void stop()
{
// do nothing
}
};
// Using Lifecycle.Stage.SERVER because DruidNodeDiscoveryProvider should be already started when
// selfDiscoveryListenerRegistrator.start() is called.
lifecycle.addHandler(selfDiscoveryListenerRegistrator, Lifecycle.Stage.SERVER);
}
);
}

/** See the description of this endpoint in api-reference.md. */
@GET
@Path("/status/selfDiscoveredStatus")
@Path("/status")
@Produces(MediaType.APPLICATION_JSON)
@ResourceFilters(StateResourceFilter.class)
public Response getSelfDiscoveredStatus()
{
return Response.ok(Collections.singletonMap("selfDiscovered", selfDiscovered.getAsBoolean())).build();
return Response.ok(Collections.singletonMap("selfDiscovered", isDiscoveredAllRoles())).build();
}

/** See the description of this endpoint in api-reference.md. */
@GET
@Path("/status/selfDiscovered")
@Produces(MediaType.APPLICATION_JSON)
@ResourceFilters(StateResourceFilter.class)
public Response getSelfDiscovered()
{
if (selfDiscovered.getAsBoolean()) {
if (isDiscoveredAllRoles()) {
return Response.ok().build();
} else {
return Response.status(HttpStatus.SERVICE_UNAVAILABLE_503).build();
}
}

private boolean isDiscoveredAllRoles()
{
return selfDiscoveredRoles.stream().allMatch(BooleanSupplier::getAsBoolean);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
public class SecurityResourceFilterTest extends ResourceFilterTestHelper
{
@Parameterized.Parameters(name = "{index}: requestPath={0}, requestMethod={1}, resourceFilter={2}")
public static Collection<Object[]> data() throws NoSuchMethodException
public static Collection<Object[]> data()
{
return ImmutableList.copyOf(
Iterables.concat(
Expand All @@ -70,8 +70,7 @@ public static Collection<Object[]> data() throws NoSuchMethodException
getRequestPathsWithAuthorizer(CoordinatorDynamicConfigsResource.class),
getRequestPathsWithAuthorizer(QueryResource.class),
getRequestPathsWithAuthorizer(StatusResource.class),
getRequestPathsWithAuthorizer(SelfDiscoveryResource.class.getDeclaredMethod("getSelfDiscoveredStatus")),
getRequestPathsWithAuthorizer(SelfDiscoveryResource.class.getDeclaredMethod("getSelfDiscovered")),
getRequestPathsWithAuthorizer(SelfDiscoveryResource.class),
getRequestPathsWithAuthorizer(BrokerQueryResource.class),
getRequestPathsWithAuthorizer(RouterResource.class)
)
Expand Down
5 changes: 1 addition & 4 deletions services/src/main/java/org/apache/druid/cli/CliBroker.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
import org.apache.druid.guice.LifecycleModule;
import org.apache.druid.guice.QueryRunnerFactoryModule;
import org.apache.druid.guice.QueryableModule;
import org.apache.druid.guice.annotations.Self;
import org.apache.druid.java.util.common.logger.Logger;
import org.apache.druid.query.QuerySegmentWalker;
import org.apache.druid.query.RetryQueryRunnerConfig;
Expand Down Expand Up @@ -123,9 +122,7 @@ protected List<? extends Module> getModules()

LifecycleModule.register(binder, Server.class);

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.BROKER);

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
DiscoverySideEffectsProvider
.builder(NodeRole.BROKER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import org.apache.druid.guice.ManageLifecycle;
import org.apache.druid.guice.annotations.CoordinatorIndexingServiceHelper;
import org.apache.druid.guice.annotations.EscalatedGlobal;
import org.apache.druid.guice.annotations.Self;
import org.apache.druid.guice.http.JettyHttpClientModule;
import org.apache.druid.java.util.common.concurrent.Execs;
import org.apache.druid.java.util.common.concurrent.ExecutorServices;
Expand Down Expand Up @@ -239,9 +238,7 @@ public void configure(Binder binder)
DruidCoordinatorCleanupPendingSegments.class
);

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.COORDINATOR);

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
Coordinator.class,
DiscoverySideEffectsProvider.builder(NodeRole.COORDINATOR).build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
import org.apache.druid.guice.QueryRunnerFactoryModule;
import org.apache.druid.guice.QueryableModule;
import org.apache.druid.guice.ServerTypeConfig;
import org.apache.druid.guice.annotations.Self;
import org.apache.druid.java.util.common.logger.Logger;
import org.apache.druid.query.QuerySegmentWalker;
import org.apache.druid.query.lookup.LookupModule;
Expand Down Expand Up @@ -104,9 +103,7 @@ protected List<? extends Module> getModules()
JsonConfigProvider.bind(binder, "druid.historical.cache", CacheConfig.class);
binder.install(new CacheModule());

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.HISTORICAL);

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
DiscoverySideEffectsProvider
.builder(NodeRole.HISTORICAL)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public void configure(Binder binder)

binder.bind(SegmentLoadDropHandler.class).toProvider(Providers.of(null));

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
DiscoverySideEffectsProvider
.builder(NodeRole.INDEXER)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,7 @@ public void configure(Binder binder)

LifecycleModule.register(binder, Server.class);

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.MIDDLE_MANAGER);

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
DiscoverySideEffectsProvider
.builder(NodeRole.MIDDLE_MANAGER)
Expand Down
5 changes: 1 addition & 4 deletions services/src/main/java/org/apache/druid/cli/CliOverlord.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
import org.apache.druid.guice.ManageLifecycle;
import org.apache.druid.guice.PolyBind;
import org.apache.druid.guice.annotations.Json;
import org.apache.druid.guice.annotations.Self;
import org.apache.druid.indexing.common.actions.LocalTaskActionClientFactory;
import org.apache.druid.indexing.common.actions.TaskActionClientFactory;
import org.apache.druid.indexing.common.actions.TaskActionToolbox;
Expand Down Expand Up @@ -248,9 +247,7 @@ public void configure(Binder binder)
LifecycleModule.register(binder, Server.class);
}

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.OVERLORD);

bindAnnouncer(
bindNodeRoleAndAnnouncer(
binder,
IndexingService.class,
DiscoverySideEffectsProvider.builder(NodeRole.OVERLORD).build()
Expand Down
7 changes: 1 addition & 6 deletions services/src/main/java/org/apache/druid/cli/CliRouter.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,7 @@ protected List<? extends Module> getModules()
LifecycleModule.register(binder, Server.class);
DiscoveryModule.register(binder, Self.class);

binder.bind(NodeRole.class).annotatedWith(Self.class).toInstance(NodeRole.ROUTER);

bindAnnouncer(
binder,
DiscoverySideEffectsProvider.builder(NodeRole.ROUTER).build()
);
bindNodeRoleAndAnnouncer(binder, DiscoverySideEffectsProvider.builder(NodeRole.ROUTER).build());

Jerseys.addResource(binder, SelfDiscoveryResource.class);
LifecycleModule.registerKey(binder, Key.get(SelfDiscoveryResource.class));
Expand Down
33 changes: 31 additions & 2 deletions services/src/main/java/org/apache/druid/cli/ServerRunnable.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Provider;
import com.google.inject.multibindings.Multibinder;
import org.apache.druid.curator.discovery.ServiceAnnouncer;
import org.apache.druid.discovery.DiscoveryDruidNode;
import org.apache.druid.discovery.DruidNodeAnnouncer;
Expand All @@ -42,6 +43,7 @@
import java.util.List;

/**
*
*/
public abstract class ServerRunnable extends GuiceRunnable
{
Expand All @@ -64,7 +66,34 @@ public void run()
}
}

public static void bindAnnouncer(
public static void bindNodeRoleAndAnnouncer(Binder binder, DiscoverySideEffectsProvider discoverySideEffectsProvider)
{
Multibinder<NodeRole> selfBinder = Multibinder.newSetBinder(binder, NodeRole.class, Self.class);
selfBinder.addBinding().toInstance(discoverySideEffectsProvider.nodeRole);

bindAnnouncer(
binder,
discoverySideEffectsProvider
);
}

public static void bindNodeRoleAndAnnouncer(
Binder binder,
Class<? extends Annotation> annotation,
DiscoverySideEffectsProvider discoverySideEffectsProvider
)
{
Multibinder<NodeRole> selfBinder = Multibinder.newSetBinder(binder, NodeRole.class, Self.class);
selfBinder.addBinding().toInstance(discoverySideEffectsProvider.nodeRole);

bindAnnouncer(
binder,
annotation,
discoverySideEffectsProvider
);
}

private static void bindAnnouncer(
final Binder binder,
final DiscoverySideEffectsProvider provider
)
Expand All @@ -76,7 +105,7 @@ public static void bindAnnouncer(
LifecycleModule.registerKey(binder, Key.get(DiscoverySideEffectsProvider.Child.class));
}

public static void bindAnnouncer(
private static void bindAnnouncer(
final Binder binder,
final Class<? extends Annotation> annotation,
final DiscoverySideEffectsProvider provider
Expand Down