GH-3256: Support Testing TCP Connections

Resolves https://github.com/spring-projects/spring-integration/issues/3256
This commit is contained in:
Gary Russell
2020-04-23 15:26:50 -04:00
committed by Artem Bilan
parent 02407f7dff
commit 1d4626f54c
6 changed files with 265 additions and 37 deletions

View File

@@ -555,6 +555,8 @@ IMPORTANT: These properties do not apply if any of the delegate factories is a `
Starting with version 5.3, these default to `Long.MAX_VALUE` and `true` so the factory only attempts to fail back when the current connection fails.
To revert to the default behavior of previous versions, set them to `0` and `false`.
Also see <<testing-connections>>.
[[tcp-affinity-cf]]
==== TCP Thread Affinity Connection Factory
@@ -592,6 +594,64 @@ public TcpOutboundGateway outGate() {
----
====
[[testing-connections]]
=== Testing Connections
In some scenarios, it can be useful to send some kind of health-check request when a connection is first opened.
One such scenario might be when using a <<failover-cf>> so that we can fail over if the selected server allowed a connection to be opened but reports that it is not healthy.
In order to support this feature, add a `connectionTest` to the client connection factory.
====
[source, java]
----
/**
* Set a {@link Predicate} that will be invoked to test a new connection; return true
* to accept the connection, false the reject.
* @param connectionTest the predicate.
* @since 5.3
*/
public void setConnectionTest(@Nullable Predicate<TcpConnectionSupport> connectionTest) {
this.connectionTest = connectionTest;
}
----
====
To test the connection, attach a temporary listener to the connection within the test.
If the test fails, the connection is closed and an exception thrown.
When used with the <<failover-cf>> this triggers trying the next server.
IMPORTANT: Only the first reply from the server will go to the test listener.
In the following example, the server is considered healthy if the server replies `PONG` when we send `PING`.
====
[source, java]
----
Message<String> ping = new GenericMessage<>("PING");
byte[] pong = "PONG".getBytes();
clientFactory.setConnectionTest(conn -> {
CountDownLatch latch = new CountDownLatch(1);
AtomicBoolean result = new AtomicBoolean();
conn.registerTestListener(msg -> {
if (Arrays.equals(pong, (byte[]) msg.getPayload())) {
result.set(true);
}
latch.countDown();
return false;
});
conn.send(ping);
try {
latch.await(10, TimeUnit.SECONDS);
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return result.get();
});
----
====
[[ip-interceptors]]
=== TCP Connection Interceptors

View File

@@ -128,6 +128,9 @@ See <<./ip.adoc#failover-cf,TCP Failover Client Connection Factory>> for more in
The `TcpOutboundGateway` now supports asynchronous request/reply.
See <<./ip.adoc#tcp-gateways,TCP Gateways>> for more information.
You can now configure client connections to perform some arbitrary test on new connections.
See <<./ip.adoc#testing-connections,Testing Connections>> for more information.
[[x5.3-rsocket]]
=== RSocket Changes