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 committed Feb 27, 2024
1 parent e2aaa0e commit 14b18b6
Show file tree
Hide file tree
Showing 11 changed files with 329 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
clusterStatsMonitorType: COORDINATOR_INFO

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
clusterStatsMonitorType: COORDINATOR_INFO

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
clusterStatsMonitorType: COORDINATOR_INFO

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

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

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

<dependency>
<groupId>io.airlift</groupId>
<artifactId>units</artifactId>
<version>1.10</version>
</dependency>

<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-assets</artifactId>
Expand Down Expand Up @@ -239,6 +255,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 @@ -506,9 +529,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
67 changes: 67 additions & 0 deletions gateway-ha/src/main/java/io/trino/client/NodeVersion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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.client;

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

import java.util.Objects;

import static java.util.Objects.requireNonNull;

// copy of https://github.com/trinodb/trino/blob/f83854687229df1ae3325249e7bcd29f03d0943c/client/trino-client/src/main/java/io/trino/client/NodeVersion.java
public class NodeVersion
{
public static final NodeVersion UNKNOWN = new NodeVersion("<unknown>");

private final String version;

@JsonCreator
public NodeVersion(@JsonProperty("version") String version)
{
this.version = requireNonNull(version, "version is null");
}

@JsonProperty
public String getVersion()
{
return version;
}

@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

NodeVersion that = (NodeVersion) o;
return Objects.equals(version, that.version);
}

@Override
public int hashCode()
{
return Objects.hash(version);
}

@Override
public String toString()
{
return version;
}
}
114 changes: 114 additions & 0 deletions gateway-ha/src/main/java/io/trino/client/ServerInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* 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.client;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.airlift.units.Duration;

import java.util.Objects;
import java.util.Optional;

import static com.google.common.base.MoreObjects.toStringHelper;
import static java.util.Objects.requireNonNull;

//copy of https://github.com/trinodb/trino/blob/f83854687229df1ae3325249e7bcd29f03d0943c/client/trino-client/src/main/java/io/trino/client/ServerInfo.java#L28
public class ServerInfo
{
private final NodeVersion nodeVersion;
private final String environment;
private final boolean coordinator;
private final boolean starting;

// optional to maintain compatibility with older servers
private final Optional<Duration> uptime;

@JsonCreator
public ServerInfo(
@JsonProperty("nodeVersion") NodeVersion nodeVersion,
@JsonProperty("environment") String environment,
@JsonProperty("coordinator") boolean coordinator,
@JsonProperty("starting") boolean starting,
@JsonProperty("uptime") Optional<Duration> uptime)
{
this.nodeVersion = requireNonNull(nodeVersion, "nodeVersion is null");
this.environment = requireNonNull(environment, "environment is null");
this.coordinator = coordinator;
this.starting = starting;
this.uptime = requireNonNull(uptime, "uptime is null");
}

@JsonProperty
public NodeVersion getNodeVersion()
{
return nodeVersion;
}

@JsonProperty
public String getEnvironment()
{
return environment;
}

@JsonProperty
public boolean isCoordinator()
{
return coordinator;
}

@JsonProperty
public boolean isStarting()
{
return starting;
}

@JsonProperty
public Optional<Duration> getUptime()
{
return uptime;
}

@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}

ServerInfo that = (ServerInfo) o;
return Objects.equals(nodeVersion, that.nodeVersion) &&
Objects.equals(environment, that.environment);
}

@Override
public int hashCode()
{
return Objects.hash(nodeVersion, environment);
}

@Override
public String toString()
{
return toStringHelper(this)
.add("nodeVersion", nodeVersion)
.add("environment", environment)
.add("coordinator", coordinator)
.add("uptime", uptime.orElse(null))
.omitNullValues()
.toString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* 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.Request;
import io.airlift.http.client.jetty.JettyHttpClient;
import io.airlift.json.JsonCodec;
import io.trino.client.ServerInfo;
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;

public class ClusterStatsInfoApiMonitor
implements ClusterStatsMonitor
{
private static HttpClient client = new JettyHttpClient(new HttpClientConfig());
private static final Logger log = LoggerFactory.getLogger(ClusterStatsInfoApiMonitor.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/status").build())
.build();

try {
ServerInfo serverInfo = client.execute(request, createJsonResponseHandler(JsonCodec.jsonCodec(ServerInfo.class)));
return !serverInfo.isStarting();
}
catch (Exception e) {
e.printStackTrace();
log.error("Exception checking {}/v1/info for health: {} ", baseUrl, e.getMessage());
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@

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

public ClusterStatsConfiguration() {}

public boolean isUseApi()
public ClusterStatsMonitorType getClusterStatsMonitorType()
{
return this.useApi;
return clusterStatsMonitorType;
}

public void setUseApi(boolean useApi)
public void setClusterStatsMonitorType(ClusterStatsMonitorType clusterStatsMonitorType)
{
this.useApi = useApi;
this.clusterStatsMonitorType = clusterStatsMonitorType;
}
}
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
}
Loading

0 comments on commit 14b18b6

Please sign in to comment.