feat: Add support for connecting to Redis clusters (#24924)
This PR adds support to Appsmith server to be able to connect to ElastiCache Redis with cluster mode turned on. When the `APPSMITH_REDIS_URL` is set to `redis://...`, the current default behaviour is preserved. But if it is set to `redis-cluster://...`, then we setup a pooled connection with cluster mod enabled.
This commit is contained in:
parent
67567e1ee7
commit
6c7ec746e9
|
|
@ -224,6 +224,14 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Needed for establishing pooled connections to ElastiCache Redis with cluster mode enabled. -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.11.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.platform</groupId>
|
||||
<artifactId>junit-platform-suite-engine</artifactId>
|
||||
|
|
@ -455,4 +463,4 @@
|
|||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -8,10 +8,17 @@ import com.fasterxml.jackson.databind.json.JsonMapper;
|
|||
import io.lettuce.core.resource.ClientResources;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
|
||||
import org.springframework.data.redis.connection.RedisClusterConfiguration;
|
||||
import org.springframework.data.redis.connection.RedisNode;
|
||||
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
|
||||
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
|
||||
import org.springframework.data.redis.connection.lettuce.observability.MicrometerTracingAdapter;
|
||||
import org.springframework.data.redis.core.ReactiveRedisOperations;
|
||||
import org.springframework.data.redis.core.ReactiveRedisTemplate;
|
||||
|
|
@ -28,9 +35,11 @@ import org.springframework.security.core.context.SecurityContextImpl;
|
|||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.session.data.redis.config.annotation.web.server.EnableRedisWebSession;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
|
|
@ -38,6 +47,9 @@ import java.util.Map;
|
|||
@EnableRedisWebSession(maxInactiveIntervalInSeconds = 2592000)
|
||||
public class RedisConfig {
|
||||
|
||||
@Value("${appsmith.redis.url:}")
|
||||
private String redisURL;
|
||||
|
||||
/**
|
||||
* This is the topic to which we will publish & subscribe to. We can have multiple topics based on the messages
|
||||
* that we wish to broadcast. Starting with a single one for now.
|
||||
|
|
@ -49,6 +61,31 @@ public class RedisConfig {
|
|||
return new ChannelTopic("appsmith:queue");
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
|
||||
final URI redisUri = URI.create(redisURL);
|
||||
final String scheme = redisUri.getScheme();
|
||||
|
||||
switch (scheme) {
|
||||
case "redis" -> {
|
||||
return new LettuceConnectionFactory(redisUri.getHost(), redisUri.getPort());
|
||||
}
|
||||
|
||||
case "redis-cluster" -> {
|
||||
// For ElastiCache Redis with cluster mode enabled, with the configuration endpoint.
|
||||
final LettuceClientConfiguration config = LettucePoolingClientConfiguration
|
||||
.builder()
|
||||
.build();
|
||||
final RedisClusterConfiguration clusterConfig = new RedisClusterConfiguration();
|
||||
clusterConfig.addClusterNode(new RedisNode(redisUri.getHost(), redisUri.getPort()));
|
||||
return new LettuceConnectionFactory(clusterConfig, config);
|
||||
}
|
||||
|
||||
default -> throw new InvalidRedisURIException("Invalid redis scheme: " + scheme);
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
|
||||
return new JSONSessionRedisSerializer();
|
||||
|
|
@ -179,4 +216,10 @@ public class RedisConfig {
|
|||
}
|
||||
}
|
||||
|
||||
private static class InvalidRedisURIException extends RuntimeException {
|
||||
public InvalidRedisURIException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ sentry.debug=false
|
|||
sentry.environment=${APPSMITH_SERVER_SENTRY_ENVIRONMENT:}
|
||||
|
||||
# Redis Properties
|
||||
spring.data.redis.url=${APPSMITH_REDIS_URL}
|
||||
appsmith.redis.url=${APPSMITH_REDIS_URL}
|
||||
|
||||
# Mail Properties
|
||||
# Email defaults to false, because, when true and the other SMTP properties are not set, Spring will try to use a
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user