DATAREDIS-731 - Share native Lettuce Cluster connection across LettuceClusterConnection.
We now share Lettuce Cluster connections if configured on LettuceConnectionFactory (enabled by default) across multiple LettuceClusterConnections. Connection sharing prevents creation and disposal of cluster connections per template command execution which improves overall performance. Original Pull Request: #297
This commit is contained in:
committed by
Christoph Strobl
parent
09bd48c245
commit
b656b09db5
@@ -24,13 +24,19 @@ import static org.springframework.data.redis.connection.ClusterTestVariables.*;
|
||||
import static org.springframework.data.redis.test.util.MockitoUtils.*;
|
||||
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.api.StatefulConnection;
|
||||
import io.lettuce.core.api.StatefulRedisConnection;
|
||||
import io.lettuce.core.api.sync.RedisCommands;
|
||||
import io.lettuce.core.cluster.RedisClusterClient;
|
||||
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
|
||||
import io.lettuce.core.cluster.api.async.RedisClusterAsyncCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisAdvancedClusterCommands;
|
||||
import io.lettuce.core.cluster.api.sync.RedisClusterCommands;
|
||||
import io.lettuce.core.cluster.models.partitions.Partitions;
|
||||
import io.lettuce.core.cluster.models.partitions.RedisClusterNode.NodeFlag;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -62,7 +68,10 @@ public class LettuceClusterConnectionUnitTests {
|
||||
|
||||
@Mock RedisClusterClient clusterMock;
|
||||
|
||||
@Mock ClusterConnectionProvider connectionProviderMock;
|
||||
@Mock ClusterCommandExecutor executorMock;
|
||||
@Mock ClusterNodeResourceProvider resourceProvider;
|
||||
@Mock StatefulRedisClusterConnection<byte[], byte[]> sharedConnectionMock;
|
||||
@Mock RedisClusterAsyncCommands<byte[], byte[]> dedicatedConnectionMock;
|
||||
@Mock RedisClusterCommands<byte[], byte[]> clusterConnection1Mock;
|
||||
@Mock RedisClusterCommands<byte[], byte[]> clusterConnection2Mock;
|
||||
@@ -346,4 +355,43 @@ public class LettuceClusterConnectionUnitTests {
|
||||
verify(clusterConnection1Mock, never()).configResetstat();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-731
|
||||
public void shouldExecuteOnSharedConnection() {
|
||||
|
||||
RedisAdvancedClusterCommands<byte[], byte[]> sync = mock(RedisAdvancedClusterCommands.class);
|
||||
|
||||
when(connectionProviderMock.getClient()).thenReturn(clusterMock);
|
||||
when(sharedConnectionMock.sync()).thenReturn(sync);
|
||||
|
||||
LettuceClusterConnection connection = new LettuceClusterConnection(sharedConnectionMock, connectionProviderMock,
|
||||
executorMock, Duration.ZERO);
|
||||
|
||||
connection.keyCommands().del(KEY_1_BYTES);
|
||||
|
||||
verify(sync).del(KEY_1_BYTES);
|
||||
verify(connectionProviderMock).getClient();
|
||||
verifyNoMoreInteractions(connectionProviderMock);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-731
|
||||
public void shouldExecuteOnDedicatedConnection() {
|
||||
|
||||
RedisCommands<byte[], byte[]> sync = mock(RedisCommands.class);
|
||||
StatefulRedisConnection<byte[], byte[]> dedicatedConnection = mock(StatefulRedisConnection.class);
|
||||
|
||||
when(connectionProviderMock.getClient()).thenReturn(clusterMock);
|
||||
when(connectionProviderMock.getConnection(StatefulConnection.class)).thenReturn(dedicatedConnection);
|
||||
when(dedicatedConnection.sync()).thenReturn(sync);
|
||||
|
||||
LettuceClusterConnection connection = new LettuceClusterConnection(sharedConnectionMock, connectionProviderMock,
|
||||
executorMock, Duration.ZERO);
|
||||
|
||||
connection.listCommands().bLPop(1, KEY_1_BYTES);
|
||||
|
||||
verify(sync).blpop(1, KEY_1_BYTES);
|
||||
verify(connectionProviderMock).getClient();
|
||||
verify(connectionProviderMock).getConnection(StatefulConnection.class);
|
||||
verifyNoMoreInteractions(connectionProviderMock);
|
||||
verifyZeroInteractions(sharedConnectionMock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.hamcrest.core.IsEqual.*;
|
||||
import static org.hamcrest.core.IsInstanceOf.*;
|
||||
import static org.hamcrest.core.IsNull.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.data.redis.connection.ClusterTestVariables.*;
|
||||
import static org.springframework.data.redis.connection.lettuce.LettuceTestClientResources.*;
|
||||
import static org.springframework.test.util.ReflectionTestUtils.*;
|
||||
@@ -29,6 +30,9 @@ import io.lettuce.core.ClientOptions;
|
||||
import io.lettuce.core.RedisClient;
|
||||
import io.lettuce.core.RedisURI;
|
||||
import io.lettuce.core.cluster.RedisClusterClient;
|
||||
import io.lettuce.core.cluster.api.StatefulRedisClusterConnection;
|
||||
import io.lettuce.core.codec.ByteArrayCodec;
|
||||
import io.lettuce.core.codec.RedisCodec;
|
||||
import io.lettuce.core.resource.ClientResources;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -38,6 +42,8 @@ import java.util.Collections;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.data.redis.ConnectionFactoryTracker;
|
||||
import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisClusterConnection;
|
||||
@@ -552,6 +558,7 @@ public class LettuceConnectionFactoryUnitTests {
|
||||
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfig);
|
||||
connectionFactory.setShutdownTimeout(0);
|
||||
connectionFactory.setTimeout(2000);
|
||||
connectionFactory.setShareNativeConnection(false);
|
||||
connectionFactory.afterPropertiesSet();
|
||||
ConnectionFactoryTracker.add(connectionFactory);
|
||||
|
||||
@@ -566,6 +573,7 @@ public class LettuceConnectionFactoryUnitTests {
|
||||
|
||||
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfig, LettuceClientConfiguration
|
||||
.builder().commandTimeout(Duration.ofSeconds(2)).shutdownTimeout(Duration.ZERO).build());
|
||||
connectionFactory.setShareNativeConnection(false);
|
||||
|
||||
connectionFactory.afterPropertiesSet();
|
||||
ConnectionFactoryTracker.add(connectionFactory);
|
||||
@@ -575,4 +583,30 @@ public class LettuceConnectionFactoryUnitTests {
|
||||
|
||||
clusterConnection.close();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-731
|
||||
public void shouldShareNativeConnectionWithCluster() {
|
||||
|
||||
RedisClusterClient clientMock = mock(RedisClusterClient.class);
|
||||
StatefulRedisClusterConnection<byte[], byte[]> connectionMock = mock(StatefulRedisClusterConnection.class);
|
||||
when(clientMock.connect(ByteArrayCodec.INSTANCE)).thenReturn(connectionMock);
|
||||
|
||||
LettuceConnectionFactory connectionFactory = new LettuceConnectionFactory(clusterConfig,
|
||||
LettuceClientConfiguration.defaultConfiguration()) {
|
||||
|
||||
@Override
|
||||
protected AbstractRedisClient createClient() {
|
||||
return clientMock;
|
||||
}
|
||||
};
|
||||
|
||||
connectionFactory.afterPropertiesSet();
|
||||
|
||||
new DirectFieldAccessor(connectionFactory).setPropertyValue("client", clientMock);
|
||||
|
||||
connectionFactory.getClusterConnection().close();
|
||||
connectionFactory.getClusterConnection().close();
|
||||
|
||||
verify(clientMock).connect(ArgumentMatchers.any(RedisCodec.class));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user