Add MaxMind circuit breaker. Finishes #38

This commit is contained in:
Colin McDonald 2016-07-10 12:17:03 -04:00
parent 53a56401e0
commit f0d8256f07
2 changed files with 44 additions and 21 deletions

View File

@ -79,6 +79,11 @@
<artifactId>vertx-redis-client</artifactId> <artifactId>vertx-redis-client</artifactId>
<version>3.3.0</version> <version>3.3.0</version>
</dependency> </dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-circuit-breaker</artifactId>
<version>3.3.0</version>
</dependency>
<!-- Google Libs --> <!-- Google Libs -->
<dependency> <dependency>

View File

@ -2,6 +2,8 @@ package net.frozenorb.apiv3.util;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.mongodb.async.SingleResultCallback; import com.mongodb.async.SingleResultCallback;
import io.vertx.circuitbreaker.CircuitBreaker;
import io.vertx.circuitbreaker.CircuitBreakerOptions;
import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions; import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.json.JsonObject; import io.vertx.core.json.JsonObject;
@ -17,32 +19,48 @@ public class MaxMindUtils {
private static final String maxMindUserId = APIv3.getConfig().getProperty("maxMind.userId"); private static final String maxMindUserId = APIv3.getConfig().getProperty("maxMind.userId");
private static final String maxMindLicenseKey = APIv3.getConfig().getProperty("maxMind.maxMindLicenseKey"); private static final String maxMindLicenseKey = APIv3.getConfig().getProperty("maxMind.maxMindLicenseKey");
private static final HttpClient httpsClient = APIv3.getVertxInstance().createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true)); private static final HttpClient httpsClient = APIv3.getVertxInstance().createHttpClient(new HttpClientOptions().setSsl(true).setTrustAll(true));
private static final CircuitBreaker breaker;
// MaxMind likes to randomly not respond, so we take advantage of the circuit breaker pattern to only
// check MaxMind periodically (while it's in a non-responsive state) to keep our average response times
// nice and low.
static {
breaker = CircuitBreaker.create("maxmind-circuit-breaker", APIv3.getVertxInstance(),
new CircuitBreakerOptions()
.setMaxFailures(5)
.setTimeout(1000) // 1 second
.setFallbackOnFailure(true)
.setResetTimeout(120_000) // 2 minutes
);
}
public static void getInsights(String ip, SingleResultCallback<MaxMindResult> callback) { public static void getInsights(String ip, SingleResultCallback<MaxMindResult> callback) {
if (1 == 1) { breaker.executeWithFallback((future) -> {
callback.onResult(null, null); String authHeader = "Basic " + Base64.getEncoder().encodeToString((maxMindUserId + ":" + maxMindLicenseKey).getBytes(Charsets.UTF_8));
return;
}
String authHeader = "Basic " + Base64.getEncoder().encodeToString((maxMindUserId + ":" + maxMindLicenseKey).getBytes(Charsets.UTF_8)); httpsClient.get(443, "geoip.maxmind.com", "/geoip/v2.1/insights/" + ip, (response) -> {
response.bodyHandler((body) -> {
JsonObject bodyJson = new JsonObject(body.toString());
httpsClient.get(443, "geoip.maxmind.com", "/geoip/v2.1/insights/" + ip, (response) -> { try {
response.bodyHandler((body) -> { MaxMindResult maxMindResult = new MaxMindResult(bodyJson);
JsonObject bodyJson = new JsonObject(body.toString()); future.complete(maxMindResult);
} catch (Exception ignored) {
future.complete(null);
}
});
try { response.exceptionHandler(future::fail);
MaxMindResult maxMindResult = new MaxMindResult(bodyJson); })
callback.onResult(maxMindResult, null); .putHeader("Authorization", authHeader)
} catch (Exception ignored) { .end();
callback.onResult(null, null); }, (ignored) -> null).setHandler((result) -> { // The (ignored) -> null section is our fallback, which just returns null (when the breaker is open)
} if (result.failed()) {
}); callback.onResult(null, result.cause());
} else {
response.exceptionHandler((error) -> callback.onResult(null, error)); callback.onResult((MaxMindResult) result.result(), null);
}) }
.putHeader("Authorization", authHeader) });
.setTimeout(1000)
.end();
} }
public static String getEnglishName(JsonObject source) { public static String getEnglishName(JsonObject source) {