/*
* Copyright 2015 Odnoklassniki Ltd, Mail.Ru Group
*
* 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 one.nio.http;
import one.nio.cluster.ServiceUnavailableException;
import one.nio.cluster.WeightCluster;
import one.nio.net.ConnectionString;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
public class HttpCluster extends WeightCluster<HttpProvider> {
protected int retries = 3;
protected int maxFailures = 5;
public void setRetries(int retries) {
this.retries = retries;
}
public void setMaxFailures(int maxFailures) {
this.maxFailures = maxFailures;
}
public void configure(String configuration) throws IOException {
Map<HttpProvider, Integer> newProviders = createProviders(configuration);
List<HttpProvider> oldProviders = replaceProviders(newProviders);
for (HttpProvider provider : oldProviders) {
provider.close();
}
}
protected Map<HttpProvider, Integer> createProviders(String configuration) throws IOException {
HashMap<HttpProvider, Integer> providers = new HashMap<HttpProvider, Integer>();
for (StringTokenizer st = new StringTokenizer(configuration); st.hasMoreElements(); ) {
HttpProvider provider = createProvider(st.nextToken());
int weight = Integer.parseInt(st.nextToken());
providers.put(provider, weight);
}
return providers;
}
protected HttpProvider createProvider(String provider) throws IOException {
return new HttpProvider(new ConnectionString(provider));
}
public Response invoke(Request request) throws ServiceUnavailableException {
if (log.isTraceEnabled()) {
log.trace(request.toString());
}
for (int i = 0; i < retries; i++) {
HttpProvider provider = getProvider();
try {
Response response = provider.invoke(request);
provider.getFailures().set(0);
return response;
} catch (Exception e) {
if (provider.getFailures().incrementAndGet() >= maxFailures) {
disableProvider(provider);
}
if ((e instanceof SocketTimeoutException || e.getCause() instanceof SocketTimeoutException) && !log.isTraceEnabled()) {
log.debug(provider + " timed out");
} else {
log.warn(provider + " invocation failed", e);
}
}
}
throw new ServiceUnavailableException("Cluster invocation failed");
}
}