
com.bodybuilding.turbine.discovery.DnsInstanceDiscovery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of turbine-plugins Show documentation
Show all versions of turbine-plugins Show documentation
Plugins for Netflix's Turbine
/*
* Copyright (C) 2015 Bodybuilding.com
*
* 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 com.bodybuilding.turbine.discovery;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.netflix.config.DynamicIntProperty;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import com.netflix.turbine.discovery.Instance;
import com.netflix.turbine.discovery.InstanceDiscovery;
import java.net.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Fork of {@link com.netflix.turbine.discovery.ConfigPropertyBasedDiscovery} that allows integer format strings (%d) in hostnames.
* The integer is incremented until 2 consecutive lookups fail. Only a single %d may be present.
*/
public class DnsInstanceDiscovery implements InstanceDiscovery {
private static final DynamicStringProperty DefaultClusterInstanceList = DynamicPropertyFactory.getInstance().getStringProperty("turbine.ConfigPropertyBasedDiscovery.default.instances", null);
private static final DynamicStringProperty ClusterList = DynamicPropertyFactory.getInstance().getStringProperty(TURBINE_AGGREGATOR_CLUSTER_CONFIG, null);
private static final DynamicIntProperty DnsMaxLookupErrors = DynamicPropertyFactory.getInstance().getIntProperty("DnsInstanceDiscovery.maxLookupErrors", 2);
private static final Splitter PropertySplitter = Splitter.on(',').omitEmptyStrings().trimResults();
@Override
public Collection getInstanceList() throws Exception {
List clusters = getClusterList();
List instances = new ArrayList<>();
for (String cluster : clusters) {
instances.addAll(getInstancesForCluster(cluster));
}
return instances;
}
private List getClusterList() throws Exception {
String clusterConfig = ClusterList.get();
if (clusterConfig == null || clusterConfig.trim().length() == 0) {
// check if there is a list of default instances. If yes, then use 'default' as the cluster
String defaultInstanceList = DefaultClusterInstanceList.get();
if (defaultInstanceList == null || defaultInstanceList.trim().length() == 0) {
throw new Exception("Must configure instance list using property: " + DefaultClusterInstanceList.getName());
}
// return cluster as default
return Lists.newArrayList("default");
}
// cluster config is not null. Parse cluster config.
List clusters = Lists.newArrayList(PropertySplitter.split(clusterConfig));
if (clusters.size() == 0) {
throw new Exception("Must configure property: " + ClusterList.getName());
}
return clusters;
}
private List getInstancesForCluster(String cluster) throws Exception {
DynamicStringProperty instanceListProp = DynamicPropertyFactory.getInstance().getStringProperty("turbine.ConfigPropertyBasedDiscovery." + cluster + ".instances", null);
String instanceList = instanceListProp.get();
if (instanceList == null || instanceList.trim().length() == 0) {
throw new Exception("Must configure Instance list property: " + instanceListProp.getName());
}
Iterable parts = PropertySplitter.split(instanceList);
List instances = new ArrayList<>();
for (String s : parts) {
instances.addAll(resolveInstances(s, cluster));
}
return instances;
}
/**
* Resolves instances using DNS if they contain %d
* @param url url to use for lookup
* @param cluster the cluster these instances belong to
* @return collection of instances that resolved
* @throws MalformedURLException
*/
private Collection extends Instance> resolveInstances(final String url, String cluster) throws MalformedURLException {
List instanceList = Lists.newArrayList();
String withSchema = url;
if (!withSchema.contains("://")) {
withSchema = "http://" + url;
}
String host = new URL(withSchema).getHost();
if(!host.contains("%")) {
return Collections.singleton(new Instance(url, cluster, true));
}
int errors = 0;
int i = 1;
do {
String newHost = String.format(host, i++);
InetAddress address = resolveHost(newHost);
if (address == null) {
errors++;
} else {
errors = 0;
instanceList.add(new Instance(url.replace(host, newHost), cluster, true));
}
} while (errors < DnsMaxLookupErrors.get());
return instanceList;
}
@VisibleForTesting
protected InetAddress resolveHost(String host) {
try {
return InetAddress.getByName(host);
} catch (UnknownHostException e) {
return null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy