Spring Boot 3 с Lettuce: как избежать команды SENTINEL REPLICAS, когда у пользователя нет разрешений?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Spring Boot 3 с Lettuce: как избежать команды SENTINEL REPLICAS, когда у пользователя нет разрешений?

Сообщение Anonymous »

Я настраиваю приложение Spring Boot 3 (с использованием Gradle и Java 17) с Redis Sentinel и клиентом Lettuce (нереактивным, с RedisTemplate).
Наша инфраструктурная группа предоставила установку Redis Sentinel (1 узел) с главным устройством и репликой, а также выделенным пользователем и паролем (+ACL). Однако при запуске приложения мы сталкиваемся с ошибкой проверки работоспособности.
PoolException: Could not get a resource from the pool
RedisConnectionException: Unable to connect to redis-sentinel://test:****@?sentinelMasterId=&timeout=3s
RedisCommandExecutionException: NOPERM User test has no permissions to run the 'sentinel|replicas' command.

Команда инфраструктуры подтверждает, что они намеренно ограничили эту команду, поскольку считают, что она служит реактивной цели, когда они обнаружили ошибку, которая не была исправлена ​​в последних версиях...
Они также предложили настроить Lettuce так, чтобы она не использовала эту команду. Это правда?
Как настроить клиент Lettuce в нереактивном приложении Spring Boot для работы без необходимости разрешения SENTINEL REPLICAS? Существуют ли определенные настройки, такие как стратегия ReadFrom или альтернативный метод конфигурации, которые позволяют избежать этой команды?
Я уверен, что это стандартное поведение как в реактивном, так и в нереактивном режимах Lettuce, и вы не можете обойтись без этой команды.
Моя конфигурация: я использую стандартную конфигурацию RedisSentinelConfiguration для настройки LettuceConnectionFactory и ЧитатьFrom.Master.
@Configuration
@ConditionalOnProperty(prefix = "app.cache.redis", name = "enabled", havingValue = "true")
@RequiredArgsConstructor
@Slf4j
public class RedisConfig {

private final CustomRedisProperties customRedisProperties;

@Bean(destroyMethod = "shutdown")
public ClientResources clientResources() {
return DefaultClientResources.create();
}

@Bean
public ClientOptions clientOptions() {
return ClientOptions.builder()
.timeoutOptions(TimeoutOptions.enabled(Duration.ofMillis(customRedisProperties.getConnectTimeout())))
.disconnectedBehavior(DisconnectedBehavior.REJECT_COMMANDS)
.pingBeforeActivateConnection(true)
.autoReconnect(true)
.build();
}

@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.build();
}

@Bean
public GenericObjectPoolConfig redisPoolConfig() {
GenericObjectPoolConfig genericObjectPoolConfig = new GenericObjectPoolConfig();
genericObjectPoolConfig.setMaxTotal(customRedisProperties.getMaxActive());
genericObjectPoolConfig.setMaxIdle(customRedisProperties.getMaxIdle());
genericObjectPoolConfig.setMinIdle(customRedisProperties.getMinIdle());
genericObjectPoolConfig.setMaxWait(Duration.ofMillis(customRedisProperties.getMaxWait()));
genericObjectPoolConfig.setTestOnBorrow(true);
genericObjectPoolConfig.setTestWhileIdle(true);
genericObjectPoolConfig.setTimeBetweenEvictionRuns(Duration.ofSeconds(30));
genericObjectPoolConfig.setMinEvictableIdleDuration(Duration.ofSeconds(60));
genericObjectPoolConfig.setNumTestsPerEvictionRun(3);
return genericObjectPoolConfig;
}

@Bean
public LettuceClientConfiguration lettuceClientConfiguration(
GenericObjectPoolConfig redisPoolConfig,
ClientOptions clientOptions,
ClientResources clientResources
) {
return LettucePoolingClientConfiguration.builder()
.poolConfig(redisPoolConfig)
.clientOptions(clientOptions)
.clientResources(clientResources)
.commandTimeout(Duration.ofMillis(customRedisProperties.getCommandTimeout()))
.readFrom(ReadFrom.UPSTREAM) //ReadFrom.MASTER
.build();
}

@Bean
public RedisConnectionFactory redisConnectionFactory(
LettuceClientConfiguration lettuceClientConfiguration
) {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration();
sentinelConfig.master(customRedisProperties.getSentinel().getMaster());

if (Objects.nonNull(customRedisProperties.getSentinel().getPassword())) {
sentinelConfig.setSentinelPassword(RedisPassword.of(customRedisProperties.getSentinel().getPassword()));
}

if (Objects.nonNull(customRedisProperties.getSentinel().getUsername())) {
sentinelConfig.setSentinelUsername(customRedisProperties.getSentinel().getUsername());
}

if (customRedisProperties.getSupportUsername()
&& Objects.nonNull(customRedisProperties.getUsername())) {
sentinelConfig.setUsername(customRedisProperties.getUsername());
}

if (Objects.nonNull(customRedisProperties.getPassword())) {
sentinelConfig.setPassword(RedisPassword.of(customRedisProperties.getPassword()));
}

customRedisProperties.getSentinel().getNodes().forEach(node -> {
final var parts = node.split(":");
sentinelConfig.sentinel(parts[0], Integer.parseInt(parts[1]));
});

final var factory = new LettuceConnectionFactory(sentinelConfig, lettuceClientConfiguration);
factory.setShareNativeConnection(false);
factory.setValidateConnection(false);

return factory;
}

@Bean
public RedisTemplate redisTemplate(
RedisConnectionFactory redisConnectionFactory,
ObjectMapper objectMapper) {
RedisTemplate template = new RedisTemplate();
final var serializer = new Jackson2JsonRedisSerializer(objectMapper, Object.class);

template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);

template.setConnectionFactory(redisConnectionFactory);

return template;
}

}


Подробнее здесь: https://stackoverflow.com/questions/797 ... n-user-lac
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»