Avoid configuring connection pooling with Lettuce Redis driver unless pool parameters are provided.

fixes #228
This commit is contained in:
Scott Frederick
2018-05-11 12:14:40 -05:00
parent 7417c15211
commit cab9f2e647
5 changed files with 59 additions and 30 deletions

View File

@@ -13,13 +13,14 @@ import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.JedisClientConfigurationBuilder;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder;
/**
* Simplified access to creating Redis service objects.
* Supports Jedis and lettuce Redis clients.
* Supports Jedis and Lettuce Redis clients.
*
* @author Ramnivas Laddad
* @author Jennifer Hickey
@@ -31,6 +32,7 @@ public class RedisConnectionFactoryCreator extends AbstractServiceConnectorCreat
private static final String JEDIS_CLASS_NAME = "redis.clients.jedis.Jedis";
private static final String LETTUCE_CLASS_NAME = "io.lettuce.core.RedisClient";
private static final String APACHE_COMMONS_POOL_CLASS_NAME = "org.apache.commons.pool2.impl.GenericObjectPoolConfig";
@Override
public RedisConnectionFactory create(RedisServiceInfo serviceInfo, ServiceConnectorConfig serviceConnectorConfig) {
@@ -54,7 +56,18 @@ public class RedisConnectionFactoryCreator extends AbstractServiceConnectorCreat
return connectionFactory;
}
else if (hasClass(LETTUCE_CLASS_NAME)) {
LettucePoolingClientConfigurationBuilder builder = LettucePoolingClientConfiguration.builder();
LettuceClientConfigurationBuilder builder;
if (serviceConnectorConfig != null && ((PooledServiceConnectorConfig) serviceConnectorConfig).getPoolConfig() != null) {
if (!hasClass(APACHE_COMMONS_POOL_CLASS_NAME)) {
throw new ServiceConnectorCreationException(String.format("Failed to create cloud Redis " +
"connection factory for %s service. Apache Commons Pool must be available on " +
"the classpath if pooling parameters are provided.", serviceInfo.getId()));
}
builder = LettucePoolingClientConfiguration.builder();
} else {
builder = LettuceClientConfiguration.builder();
}
RedisLettuceClientConfigurer clientConfigurer = new RedisLettuceClientConfigurer();
if (serviceConnectorConfig instanceof RedisConnectionFactoryConfig) {
@@ -68,10 +81,10 @@ public class RedisConnectionFactoryCreator extends AbstractServiceConnectorCreat
return connectionFactory;
}
else {
throw new ServiceConnectorCreationException(String.format("Failed to create cloud Redis connection factory " +
"for %s service. No client implementation classes "
+ " of jedis or lettuce clients implementation (%s, %s) not found", serviceInfo.getId(),
JEDIS_CLASS_NAME, LETTUCE_CLASS_NAME));
throw new ServiceConnectorCreationException(String.format("Failed to create cloud Redis " +
"connection factory for %s service. No client implementation classes " +
" of Jedis or Lettuce clients implementation (%s, %s) not found",
serviceInfo.getId(), JEDIS_CLASS_NAME, LETTUCE_CLASS_NAME));
}
}
}

View File

@@ -18,7 +18,7 @@ import org.springframework.data.redis.connection.jedis.JedisClientConfiguration.
*/
public class RedisJedisClientConfigurer implements ServiceConnectorConfigurer<JedisClientConfigurationBuilder, RedisConnectionFactoryConfig> {
private MapServiceConnectionConfigurer<JedisClientConfigurationBuilder, MapServiceConnectorConfig> mapClientConfigurer =
new MapServiceConnectionConfigurer<JedisClientConfigurationBuilder, MapServiceConnectorConfig>();
new MapServiceConnectionConfigurer<>();
@Override
public JedisClientConfigurationBuilder configure(JedisClientConfigurationBuilder clientConfiguration, RedisConnectionFactoryConfig config) {

View File

@@ -1,6 +1,7 @@
package org.springframework.cloud.service.keyval;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration.LettuceClientConfigurationBuilder;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.LettucePoolingClientConfigurationBuilder;
import org.springframework.beans.BeanWrapper;
@@ -16,12 +17,12 @@ import org.springframework.cloud.service.Util;
* @author Scott Frederick
*
*/
public class RedisLettuceClientConfigurer implements ServiceConnectorConfigurer<LettucePoolingClientConfigurationBuilder, RedisConnectionFactoryConfig> {
private MapServiceConnectionConfigurer<LettucePoolingClientConfigurationBuilder, MapServiceConnectorConfig> mapClientConfigurer =
new MapServiceConnectionConfigurer<LettucePoolingClientConfigurationBuilder, MapServiceConnectorConfig>();
public class RedisLettuceClientConfigurer implements ServiceConnectorConfigurer<LettuceClientConfigurationBuilder, RedisConnectionFactoryConfig> {
private MapServiceConnectionConfigurer<LettuceClientConfigurationBuilder, MapServiceConnectorConfig> mapClientConfigurer =
new MapServiceConnectionConfigurer<>();
@Override
public LettucePoolingClientConfigurationBuilder configure(LettucePoolingClientConfigurationBuilder clientConfiguration, RedisConnectionFactoryConfig config) {
public LettuceClientConfigurationBuilder configure(LettuceClientConfigurationBuilder clientConfiguration, RedisConnectionFactoryConfig config) {
if (config != null) {
configurePool(clientConfiguration, config);
configureClient(clientConfiguration, config);
@@ -29,25 +30,25 @@ public class RedisLettuceClientConfigurer implements ServiceConnectorConfigurer<
return clientConfiguration;
}
public LettucePoolingClientConfigurationBuilder configure(LettucePoolingClientConfigurationBuilder clientConfiguration, PooledServiceConnectorConfig config) {
public LettuceClientConfigurationBuilder configure(LettuceClientConfigurationBuilder clientConfiguration, PooledServiceConnectorConfig config) {
if (config != null) {
configurePool(clientConfiguration, config);
}
return clientConfiguration;
}
private void configurePool(LettucePoolingClientConfigurationBuilder clientConfiguration, PooledServiceConnectorConfig config) {
private void configurePool(LettuceClientConfigurationBuilder clientConfiguration, PooledServiceConnectorConfig config) {
if (config.getPoolConfig() != null) {
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
BeanWrapper target = new BeanWrapperImpl(poolConfig);
BeanWrapper source = new BeanWrapperImpl(config.getPoolConfig());
Util.setCorrespondingProperties(target, source);
clientConfiguration.poolConfig(poolConfig);
((LettucePoolingClientConfigurationBuilder) clientConfiguration).poolConfig(poolConfig);
}
}
private void configureClient(LettucePoolingClientConfigurationBuilder clientConfiguration, RedisConnectionFactoryConfig config) {
private void configureClient(LettuceClientConfigurationBuilder clientConfiguration, RedisConnectionFactoryConfig config) {
if (config.getConnectionProperties() != null) {
mapClientConfigurer.configure(clientConfiguration, config.getConnectionProperties());
}

View File

@@ -7,7 +7,9 @@ import org.springframework.data.redis.connection.lettuce.LettuceClientConfigurat
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import static org.junit.Assert.assertEquals;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
/**
*
@@ -17,27 +19,25 @@ import static org.junit.Assert.assertEquals;
*/
public class RedisConnectionFactoryCloudConfigTestHelper extends CommonPoolCloudConfigTestHelper {
public static void assertNoPoolProperties(RedisConnectionFactory connector) {
if (connector instanceof JedisConnectionFactory) {
assertFalse(((JedisConnectionFactory) connector).getUsePool());
} else if (connector instanceof LettuceConnectionFactory) {
LettuceClientConfiguration config = ((LettuceConnectionFactory) connector).getClientConfiguration();
assertThat(config, instanceOf(LettuceClientConfiguration.class));
}
}
public static void assertPoolProperties(RedisConnectionFactory connector, int maxActive, int minIdle, long maxWait) {
GenericObjectPoolConfig poolConfig = null;
if (connector instanceof JedisConnectionFactory) {
poolConfig = ((JedisConnectionFactory) connector).getPoolConfig();
} else if (connector instanceof LettuceConnectionFactory) {
LettuceClientConfiguration config = ((LettuceConnectionFactory) connector).getClientConfiguration();
if (config instanceof LettucePoolingClientConfiguration) {
poolConfig = ((LettucePoolingClientConfiguration) config).getPoolConfig();
}
assertThat(config, instanceOf(LettucePoolingClientConfiguration.class));
poolConfig = ((LettucePoolingClientConfiguration) config).getPoolConfig();
}
assertCommonsPoolProperties(poolConfig, maxActive, minIdle, maxWait);
}
public static void assertConnectionProperties(RedisConnectionFactory connector, int timeout) {
if (connector instanceof JedisConnectionFactory) {
JedisConnectionFactory connectionFactory = (JedisConnectionFactory) connector;
assertEquals(timeout, connectionFactory.getTimeout());
} else if (connector instanceof LettuceConnectionFactory) {
LettuceConnectionFactory connectionFactory = (LettuceConnectionFactory) connector;
assertEquals(timeout, connectionFactory.getTimeout());
}
}
}

View File

@@ -27,6 +27,16 @@ public class RedisConnectionFactoryJavaConfigTest extends AbstractServiceJavaCon
return RedisConnectionFactory.class;
}
@Test
public void cloudRedisConnectionFactoryWithNoPool() {
ApplicationContext testContext =
getTestApplicationContext(RedisConnectionFactoryConfigWithServiceConfig.class,
createService("my-service"));
RedisConnectionFactory connector = testContext.getBean("noPool", getConnectorType());
RedisConnectionFactoryCloudConfigTestHelper.assertNoPoolProperties(connector);
}
@Test
public void cloudRedisConnectionFactoryWithMaxPool() {
ApplicationContext testContext =
@@ -63,6 +73,11 @@ class RedisConnectionFactoryConfigWithoutId extends AbstractCloudConfig {
}
class RedisConnectionFactoryConfigWithServiceConfig extends AbstractCloudConfig {
@Bean
public RedisConnectionFactory noPool() {
return connectionFactory().redisConnectionFactory("my-service", null);
}
@Bean
public RedisConnectionFactory pool20Wait200() {
PoolConfig poolConfig = new PoolConfig(20, 200);