本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
以下 Java 範例示範如何使用重新連線邏輯來連線至 Gemlin 用戶端,以從非預期的中斷連線回復。
它具有下列相依性:
<dependency>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>gremlin-driver</artifactId>
<version>${gremlin.version}</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>amazon-neptune-sigv4-signer</artifactId>
<version>${sig4.signer.version}</version>
</dependency>
<dependency>
<groupId>com.evanlennick</groupId>
<artifactId>retry4j</artifactId>
<version>0.15.0</version>
</dependency>
以下是範例程式碼:
重要
來自 Retry4j 的 CallExecutor
可能不是執行緒安全的程式碼。請考慮讓每個執行緒使用自己的CallExecutor
執行個體,或使用不同的重試程式庫。
注意
下列範例已更新為包含 requestInterceptor() 的使用。這已在 TinkerPop 3.6.6 中新增。在 TinkerPop 3.6.6 版之前,程式碼範例使用 handshakeInterceptor(),該版本已棄用。
public static void main(String args[]) {
boolean useIam = true;
// Create Gremlin cluster and traversal source
Cluster.Builder builder = Cluster.build()
.addContactPoint(System.getenv("neptuneEndpoint"))
.port(Integer.parseInt(System.getenv("neptunePort")))
.enableSsl(true)
.minConnectionPoolSize(1)
.maxConnectionPoolSize(1)
.serializer(Serializers.GRAPHBINARY_V1D0)
.reconnectInterval(2000);
if (useIam) {
builder.requestInterceptor( r -> {
try {
NeptuneNettyHttpSigV4Signer sigV4Signer =
new NeptuneNettyHttpSigV4Signer("(your region)", new DefaultAWSCredentialsProviderChain());
sigV4Signer.signRequest(r);
} catch (NeptuneSigV4SignerException e) {
throw new RuntimeException("Exception occurred while signing the request", e);
}
return r;
});
}
Cluster cluster = builder.create();
GraphTraversalSource g = AnonymousTraversalSource
.traversal()
.withRemote(DriverRemoteConnection.using(cluster));
// Configure retries
RetryConfig retryConfig = new RetryConfigBuilder()
.retryOnCustomExceptionLogic(getRetryLogic())
.withDelayBetweenTries(1000, ChronoUnit.MILLIS)
.withMaxNumberOfTries(5)
.withFixedBackoff()
.build();
@SuppressWarnings("unchecked")
CallExecutor<Object> retryExecutor = new CallExecutorBuilder<Object>()
.config(retryConfig)
.build();
// Do lots of queries
for (int i = 0; i < 100; i++){
String id = String.valueOf(i);
@SuppressWarnings("unchecked")
Callable<Object> query = () -> g.V(id)
.fold()
.coalesce(
unfold(),
addV("Person").property(T.id, id))
.id().next();
// Retry query
// If there are connection failures, the Java Gremlin client will automatically
// attempt to reconnect in the background, so all we have to do is wait and retry.
Status<Object> status = retryExecutor.execute(query);
System.out.println(status.getResult().toString());
}
cluster.close();
}
private static Function<Exception, Boolean> getRetryLogic() {
return e -> {
Class<? extends Exception> exceptionClass = e.getClass();
StringWriter stringWriter = new StringWriter();
String message = stringWriter.toString();
if (RemoteConnectionException.class.isAssignableFrom(exceptionClass)){
System.out.println("Retrying because RemoteConnectionException");
return true;
}
// Check for connection issues
if (message.contains("Timed out while waiting for an available host") ||
message.contains("Timed-out") && message.contains("waiting for connection on Host") ||
message.contains("Connection to server is no longer active") ||
message.contains("Connection reset by peer") ||
message.contains("SSLEngine closed already") ||
message.contains("Pool is shutdown") ||
message.contains("ExtendedClosedChannelException") ||
message.contains("Broken pipe") ||
message.contains(System.getenv("neptuneEndpoint")))
{
System.out.println("Retrying because connection issue");
return true;
};
// Concurrent writes can sometimes trigger a ConcurrentModificationException.
// In these circumstances you may want to backoff and retry.
if (message.contains("ConcurrentModificationException")) {
System.out.println("Retrying because ConcurrentModificationException");
return true;
}
// If the primary fails over to a new instance, existing connections to the old primary will
// throw a ReadOnlyViolationException. You may want to back and retry.
if (message.contains("ReadOnlyViolationException")) {
System.out.println("Retrying because ReadOnlyViolationException");
return true;
}
System.out.println("Not a retriable error");
return false;
};
}