Skip to content

Commit

Permalink
Get cluster health from v1/info
Browse files Browse the repository at this point in the history
  • Loading branch information
willmostly authored and ebyhr committed Mar 6, 2024
1 parent 8bd5e90 commit 5337e20
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 28 deletions.
6 changes: 1 addition & 5 deletions docs/quickstart-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ dataStore:
driver: org.postgresql.Driver

clusterStatsConfiguration:
useApi: true

backendState:
username: gateway
ssl: false
monitorType: INFO_API

modules:
- io.trino.gateway.ha.module.HaGatewayProviderModule
Expand Down
6 changes: 1 addition & 5 deletions gateway-ha/gateway-ha-config-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ dataStore:
driver: org.postgresql.Driver
queryHistoryHoursRetention: 24

backendState:
username: lb_query
ssl: false

clusterStatsConfiguration:
useApi: true
monitorType: INFO_API

server:
applicationConnectors:
Expand Down
6 changes: 1 addition & 5 deletions gateway-ha/gateway-ha-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@ dataStore:
driver: org.postgresql.Driver
queryHistoryHoursRetention: 24

backendState:
username: lb_query
ssl: false

clusterStatsConfiguration:
useApi: true
monitorType: INFO_API

server:
applicationConnectors:
Expand Down
32 changes: 31 additions & 1 deletion gateway-ha/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,16 @@
</exclusions>
</dependency>

<dependency>
<groupId>io.airlift</groupId>
<artifactId>http-client</artifactId>
</dependency>

<dependency>
<groupId>io.airlift</groupId>
<artifactId>json</artifactId>
</dependency>

<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-assets</artifactId>
Expand Down Expand Up @@ -235,6 +245,13 @@
<artifactId>jakarta.ws.rs-api</artifactId>
</dependency>

<!-- Prevent a ClassNotFoundException caused by io.dropwizard.jackson.Jackson:newObjectMapper
calling findModules() indiscriminately-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
Expand Down Expand Up @@ -502,9 +519,22 @@
</executions>
</plugin>

<!-- maven shade plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<configuration>
<ignoredDependencies>
<ignoredDependency>joda-time:joda-time</ignoredDependency>
</ignoredDependencies>
</configuration>
</execution>
</executions>
</plugin>

<!-- maven shade plugin -->
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.trino.gateway.ha.clustermonitor;

import io.airlift.http.client.HttpClient;
import io.airlift.http.client.HttpClientConfig;
import io.airlift.http.client.JsonResponseHandler;
import io.airlift.http.client.Request;
import io.airlift.http.client.jetty.JettyHttpClient;
import io.trino.gateway.ha.config.ProxyBackendConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;

import static io.airlift.http.client.HttpUriBuilder.uriBuilderFrom;
import static io.airlift.http.client.JsonResponseHandler.createJsonResponseHandler;
import static io.airlift.http.client.Request.Builder.prepareGet;
import static io.airlift.json.JsonCodec.jsonCodec;

public class ClusterStatsInfoApiMonitor
implements ClusterStatsMonitor
{
//TODO: make client options configurable
private static final HttpClient client = new JettyHttpClient(new HttpClientConfig());
private static final Logger log = LoggerFactory.getLogger(ClusterStatsInfoApiMonitor.class);
private static final JsonResponseHandler<ServerInfo> SERVER_INFO_JSON_RESPONSE_HANDLER = createJsonResponseHandler(jsonCodec(ServerInfo.class));

@Override
public ClusterStats monitor(ProxyBackendConfiguration backend)
{
return ClusterStats.builder(backend.getName()).healthy(isReadyStatus(backend.getProxyTo()))
.proxyTo(backend.getProxyTo())
.externalUrl(backend.getExternalUrl())
.routingGroup(backend.getRoutingGroup()).build();
}

private boolean isReadyStatus(String baseUrl)
{
Request request = prepareGet()
.setUri(uriBuilderFrom(URI.create(baseUrl)).appendPath("/v1/info").build())
.build();

try {
ServerInfo serverInfo = client.execute(request, SERVER_INFO_JSON_RESPONSE_HANDLER);
return !serverInfo.isStarting();
}
catch (Exception e) {
log.error("Exception checking {} for health: {} ", request.getUri(), e.getMessage());
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.trino.gateway.ha.clustermonitor;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import static java.util.Objects.requireNonNull;

// based on https://github.com/trinodb/trino/blob/439/client/trino-client/src/main/java/io/trino/client/ServerInfo.java
// without unused fields
public class ServerInfo
{
private final Boolean starting;

@JsonCreator
public ServerInfo(
@JsonProperty("starting") Boolean starting)
{
this.starting = requireNonNull(starting, "starting is null");
}

public boolean isStarting()
{
return starting;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@

public class ClusterStatsConfiguration
{
private boolean useApi;
private ClusterStatsMonitorType monitorType;

public ClusterStatsConfiguration() {}

public boolean isUseApi()
public ClusterStatsMonitorType getMonitorType()
{
return this.useApi;
return monitorType;
}

public void setUseApi(boolean useApi)
public void setMonitorType(ClusterStatsMonitorType monitorType)
{
this.useApi = useApi;
this.monitorType = monitorType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.trino.gateway.ha.config;

public enum ClusterStatsMonitorType
{
NOOP,
INFO_API,
UI_API,
JDBC
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import io.dropwizard.core.setup.Environment;
import io.trino.gateway.baseapp.AppModule;
import io.trino.gateway.ha.clustermonitor.ClusterStatsHttpMonitor;
import io.trino.gateway.ha.clustermonitor.ClusterStatsInfoApiMonitor;
import io.trino.gateway.ha.clustermonitor.ClusterStatsJdbcMonitor;
import io.trino.gateway.ha.clustermonitor.ClusterStatsMonitor;
import io.trino.gateway.ha.clustermonitor.NoopClusterStatsMonitor;
Expand All @@ -41,13 +42,13 @@ public ClusterStatsMonitor getClusterStatsMonitor()
{
ClusterStatsConfiguration clusterStatsConfig = config.getClusterStatsConfiguration();
if (config.getBackendState() == null) {
return new NoopClusterStatsMonitor();
}
if (clusterStatsConfig.isUseApi()) {
return new ClusterStatsHttpMonitor(config.getBackendState());
}
else {
return new ClusterStatsJdbcMonitor(config.getBackendState());
return new ClusterStatsInfoApiMonitor();
}
return switch (clusterStatsConfig.getMonitorType()) {
case INFO_API -> new ClusterStatsInfoApiMonitor();
case UI_API -> new ClusterStatsHttpMonitor(config.getBackendState());
case JDBC -> new ClusterStatsJdbcMonitor(config.getBackendState());
case NOOP -> new NoopClusterStatsMonitor();
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ public void testJdbcMonitor()
testClusterStatsMonitor(ClusterStatsJdbcMonitor::new);
}

@Test
public void testInfoApiMonitor()
{
testClusterStatsMonitor(ignored -> new ClusterStatsInfoApiMonitor());
}

private void testClusterStatsMonitor(Function<BackendStateConfiguration, ClusterStatsMonitor> monitorFactory)
{
BackendStateConfiguration backendStateConfiguration = new BackendStateConfiguration();
Expand Down

0 comments on commit 5337e20

Please sign in to comment.