DATAREDIS-682 - Connect to Redis using unix domain sockets.
We now support Redis connections using OS-native transports through unix domain sockets when using the Lettuce driver. Domain sockets do not require a roundtrip through the networking layer but directly use native epoll or kqueue interfaces.
LettuceConnectionFactory factory = new LettuceConnectionFactory(new RedisSocketConfiguration("/var/run/redis.sock"));
Unix domain socket support requires netty's native epoll/kqueue dependencies matching the runtime environment:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-x86_64</classifier>
<version>${netty}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-kqueue</artifactId>
<classifier>osx-x86_64</classifier>
<version>${netty}</version>
</dependency>
Original Pull Request: #286
This commit is contained in:
committed by
Christoph Strobl
parent
5c16a6044c
commit
d08ab93421
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.data.redis.connection;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Configuration class used for setting up {@link RedisConnection} via {@link RedisConnectionFactory} by connecting to a
|
||||
* single node <a href="http://redis.io/">Redis</a> using a local unix domain socket.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.1
|
||||
*/
|
||||
public class RedisSocketConfiguration {
|
||||
|
||||
private static final String DEFAULT_SOCKET = "/tmp/redis.sock";
|
||||
|
||||
private String socket = DEFAULT_SOCKET;
|
||||
private int database;
|
||||
private RedisPassword password = RedisPassword.none();
|
||||
|
||||
/**
|
||||
* Create a new default {@link RedisSocketConfiguration}.
|
||||
*/
|
||||
public RedisSocketConfiguration() {}
|
||||
|
||||
/**
|
||||
* Create a new {@link RedisSocketConfiguration} given {@code socket}.
|
||||
*
|
||||
* @param socket must not be {@literal null} or empty.
|
||||
*/
|
||||
public RedisSocketConfiguration(String socket) {
|
||||
|
||||
Assert.hasText(socket, "Socket path must not be null or empty!");
|
||||
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return path to the Redis socket.
|
||||
*/
|
||||
public String getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param socket path to the Redis socket.
|
||||
*/
|
||||
public void setSocket(String socket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the db index.
|
||||
*/
|
||||
public int getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the index of the database used by this connection factory. Default is 0.
|
||||
*
|
||||
* @param index database index.
|
||||
*/
|
||||
public void setDatabase(int index) {
|
||||
|
||||
Assert.isTrue(index >= 0, () -> String.format("Invalid DB index '%s' (a positive index required)", index));
|
||||
|
||||
this.database = index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return never {@literal null}.
|
||||
*/
|
||||
public RedisPassword getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param password must not be {@literal null}.
|
||||
*/
|
||||
public void setPassword(RedisPassword password) {
|
||||
|
||||
Assert.notNull(password, "RedisPassword must not be null!");
|
||||
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -67,6 +67,7 @@ import org.springframework.util.ClassUtils;
|
||||
* {@link LettuceConnectionFactory client configuration}. Lettuce supports the following environmental configurations:
|
||||
* <ul>
|
||||
* <li>{@link RedisStandaloneConfiguration}</li>
|
||||
* <li>{@link RedisSocketConfiguration}</li>
|
||||
* <li>{@link RedisSentinelConfiguration}</li>
|
||||
* <li>{@link RedisClusterConfiguration}</li>
|
||||
* </ul>
|
||||
@@ -99,6 +100,7 @@ public class LettuceConnectionFactory
|
||||
private final Object connectionMonitor = new Object();
|
||||
private boolean convertPipelineAndTxResults = true;
|
||||
private RedisStandaloneConfiguration standaloneConfig = new RedisStandaloneConfiguration("localhost", 6379);
|
||||
private @Nullable RedisSocketConfiguration socketConfiguration;
|
||||
private @Nullable RedisSentinelConfiguration sentinelConfiguration;
|
||||
private @Nullable RedisClusterConfiguration clusterConfiguration;
|
||||
private @Nullable ClusterCommandExecutor clusterCommandExecutor;
|
||||
@@ -138,7 +140,17 @@ public class LettuceConnectionFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LettuceConnectionFactory} instance using the given {@link RedisSentinelConfiguration}
|
||||
* Constructs a new {@link LettuceConnectionFactory} instance using the given {@link RedisSocketConfiguration}.
|
||||
*
|
||||
* @param socketConfiguration must not be {@literal null}.
|
||||
* @since 2.1
|
||||
*/
|
||||
public LettuceConnectionFactory(RedisSocketConfiguration socketConfiguration) {
|
||||
this(socketConfiguration, new MutableLettuceClientConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LettuceConnectionFactory} instance using the given {@link RedisSentinelConfiguration}.
|
||||
*
|
||||
* @param sentinelConfiguration must not be {@literal null}.
|
||||
* @since 1.6
|
||||
@@ -186,6 +198,24 @@ public class LettuceConnectionFactory
|
||||
this.standaloneConfig = standaloneConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LettuceConnectionFactory} instance using the given {@link RedisSocketConfiguration} and
|
||||
* {@link LettuceClientConfiguration}.
|
||||
*
|
||||
* @param socketConfiguration must not be {@literal null}.
|
||||
* @param clientConfig must not be {@literal null}.
|
||||
* @since 2.1
|
||||
*/
|
||||
public LettuceConnectionFactory(RedisSocketConfiguration socketConfiguration,
|
||||
LettuceClientConfiguration clientConfig) {
|
||||
|
||||
this(clientConfig);
|
||||
|
||||
Assert.notNull(socketConfiguration, "RedisSocketConfiguration must not be null!");
|
||||
|
||||
this.socketConfiguration = socketConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link LettuceConnectionFactory} instance using the given {@link RedisSentinelConfiguration} and
|
||||
* {@link LettuceClientConfiguration}.
|
||||
@@ -588,6 +618,10 @@ public class LettuceConnectionFactory
|
||||
*/
|
||||
public int getDatabase() {
|
||||
|
||||
if (isDomainSocketAware()) {
|
||||
return socketConfiguration.getDatabase();
|
||||
}
|
||||
|
||||
if (isRedisSentinelAware()) {
|
||||
return sentinelConfiguration.getDatabase();
|
||||
}
|
||||
@@ -604,6 +638,11 @@ public class LettuceConnectionFactory
|
||||
|
||||
Assert.isTrue(index >= 0, "invalid DB index (a positive index required)");
|
||||
|
||||
if (isDomainSocketAware()) {
|
||||
socketConfiguration.setDatabase(index);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRedisSentinelAware()) {
|
||||
sentinelConfiguration.setDatabase(index);
|
||||
return;
|
||||
@@ -648,6 +687,10 @@ public class LettuceConnectionFactory
|
||||
|
||||
private RedisPassword getRedisPassword() {
|
||||
|
||||
if (isDomainSocketAware()) {
|
||||
return socketConfiguration.getPassword();
|
||||
}
|
||||
|
||||
if (isRedisSentinelAware()) {
|
||||
return sentinelConfiguration.getPassword();
|
||||
}
|
||||
@@ -669,6 +712,11 @@ public class LettuceConnectionFactory
|
||||
@Deprecated
|
||||
public void setPassword(String password) {
|
||||
|
||||
if (isDomainSocketAware()) {
|
||||
socketConfiguration.setPassword(RedisPassword.of(password));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRedisSentinelAware()) {
|
||||
sentinelConfiguration.setPassword(RedisPassword.of(password));
|
||||
return;
|
||||
@@ -745,6 +793,15 @@ public class LettuceConnectionFactory
|
||||
return standaloneConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link RedisSocketConfiguration}.
|
||||
* @since 2.1
|
||||
*/
|
||||
@Nullable
|
||||
public RedisSocketConfiguration getSocketConfiguration() {
|
||||
return socketConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link RedisStandaloneConfiguration}, may be {@literal null}.
|
||||
* @since 2.0
|
||||
@@ -793,6 +850,14 @@ public class LettuceConnectionFactory
|
||||
return sentinelConfiguration != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true when {@link RedisSocketConfiguration} is present.
|
||||
* @since 2.1
|
||||
*/
|
||||
private boolean isDomainSocketAware() {
|
||||
return socketConfiguration != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true when {@link RedisClusterConfiguration} is present.
|
||||
* @since 1.7
|
||||
@@ -833,6 +898,7 @@ public class LettuceConnectionFactory
|
||||
}
|
||||
|
||||
private LettuceConnectionProvider doConnectionProvider(AbstractRedisClient client, RedisCodec<?, ?> codec) {
|
||||
|
||||
if (isClusterAware()) {
|
||||
return new ClusterConnectionProvider((RedisClusterClient) client, codec);
|
||||
}
|
||||
@@ -871,7 +937,8 @@ public class LettuceConnectionFactory
|
||||
return clusterClient;
|
||||
}
|
||||
|
||||
RedisURI uri = createRedisURIAndApplySettings(getHostName(), getPort());
|
||||
RedisURI uri = isDomainSocketAware() ? createRedisSocketURIAndApplySettings(socketConfiguration.getSocket())
|
||||
: createRedisURIAndApplySettings(getHostName(), getPort());
|
||||
RedisClient redisClient = clientConfiguration.getClientResources() //
|
||||
.map(clientResources -> RedisClient.create(clientResources, uri)) //
|
||||
.orElseGet(() -> RedisClient.create(uri));
|
||||
@@ -906,6 +973,16 @@ public class LettuceConnectionFactory
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private RedisURI createRedisSocketURIAndApplySettings(String socketPath) {
|
||||
|
||||
RedisURI.Builder builder = RedisURI.Builder.socket(socketPath);
|
||||
|
||||
getRedisPassword().toOptional().ifPresent(builder::withPassword);
|
||||
builder.withTimeout(clientConfiguration.getCommandTimeout());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RedisSentinelConnection getSentinelConnection() {
|
||||
return new LettuceSentinelConnection(connectionProvider);
|
||||
|
||||
Reference in New Issue
Block a user