无法连接到Redis;嵌套的异常是io.莴苣.core.RedisConnectionException,使用的是ReactiveRedisTemplate
我不熟悉反应式编程。我需要连接到Redis来保存和获取一些数据。redis实例存在于云中。 我使用连接工厂建立连接 建立到redis的连接时,请求失败。 以下是我的Redis配置类:无法连接到Redis;嵌套的异常是io.莴苣.core.RedisConnectionException,使用的是ReactiveRedisTemplate,redis,reactive,spring-data-redis,lettuce,spring-data-redis-reactive,Redis,Reactive,Spring Data Redis,Lettuce,Spring Data Redis Reactive,我不熟悉反应式编程。我需要连接到Redis来保存和获取一些数据。redis实例存在于云中。 我使用连接工厂建立连接 建立到redis的连接时,请求失败。 以下是我的Redis配置类: package com.sap.slh.tax.attributes.determination.springwebfluxdemo.config; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframewor
package com.sap.slh.tax.attributes.determination.springwebfluxdemo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableAsync;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxDetails;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxLine;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.util.JsonUtil;
@Configuration
@EnableAsync
public class RedisConfig {
private static final Logger log = LoggerFactory.getLogger(RedisConfig.class);
@Value("${vcap.services.redis.credentials.hostname:10.11.241.101}")
private String host;
@Value("${vcap.services.redis.credentials.port:36516}")
private int port;
@Value("$vcap.services.redis.credentials.password:123456788")
private String password;
@Bean
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(host, port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
redisStandaloneConfiguration.setDatabase(0);
log.error("Redis standalone configuration{}",JsonUtil.toJsonString(redisStandaloneConfiguration));
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder().build();
LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration, clientConfig);
lettuceConnectionFactory.afterPropertiesSet();
return lettuceConnectionFactory;
}
@Bean
ReactiveRedisOperations<TaxDetails, TaxLine> redisOperations(
ReactiveRedisConnectionFactory reactiveRedisConnectionFactory) {
Jackson2JsonRedisSerializer<TaxDetails> serializer = new Jackson2JsonRedisSerializer<>(TaxDetails.class);
Jackson2JsonRedisSerializer<TaxLine> serializer1 = new Jackson2JsonRedisSerializer<>(TaxLine.class);
RedisSerializationContext.RedisSerializationContextBuilder<TaxDetails, TaxLine> builder = RedisSerializationContext
.newSerializationContext(new StringRedisSerializer());
RedisSerializationContext<TaxDetails, TaxLine> context = builder.key(serializer).value(serializer1).build();
;
return new ReactiveRedisTemplate<>(
reactiveRedisConnectionFactory, context);
}
}
package com.sap.slh.tax.attributes.determination.springwebfluxdemo.config;
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.beans.factory.annotation.Value;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.data.redis.connection.reactiveDisconnectionFactory;
导入org.springframework.data.redis.connection.RedisPassword;
导入org.springframework.data.redis.connection.redistandaloneConfiguration;
导入org.springframework.data.redis.connection.莴苣.LettuceClientConfiguration;
导入org.springframework.data.redis.connection.莴苣.LettuceConnectionFactory;
导入org.springframework.data.redis.core.ReactiveRedisOperations;
导入org.springframework.data.redis.core.ReactiveRedisTemplate;
导入org.springframework.data.redis.serializer.jackson2json重新序列化器;
导入org.springframework.data.redis.serializer.RedisSerializationContext;
导入org.springframework.data.redis.serializer.StringRedisSerializer;
导入org.springframework.scheduling.annotation.EnableAsync;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxDetails;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxLine;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.util.JsonUtil;
@配置
@使能同步
公共类RedisConfig{
私有静态最终记录器log=LoggerFactory.getLogger(RedisConfig.class);
@值(${vcap.services.redis.credentials.hostname:10.11.241.101}”)
私有字符串主机;
@值(${vcap.services.redis.credentials.port:36516}”)
专用int端口;
@值($vcap.services.redis.credentials.password:123456788)
私有字符串密码;
@豆子
公共reactiveDisconnectionFactory reactiveDisconnectionFactory(){
RedisStandaloneConfiguration RedisStandaloneConfiguration=新的RedisStandaloneConfiguration(主机、端口);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
设置数据库(0);
log.error(“Redis standalone configuration{}”,JsonUtil.toJsonString(redisStandaloneConfiguration));
LettuceClientConfiguration clientConfig=LettuceClientConfiguration.builder().build();
LettuceConnectionFactory LettuceConnectionFactory=新的LettuceConnectionFactory(重新标准化配置,客户端配置);
lettuceConnectionFactory.afterPropertiesSet();
退耕还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林还林;
}
@豆子
反应器操作(
反应器连接工厂(反应器连接工厂){
Jackson2JsonRedisSerializer serializer=新的Jackson2JsonRedisSerializer(TaxDetails.class);
Jackson2JsonRedisSerializer serializer1=新的Jackson2JsonRedisSerializer(TaxLine.class);
RedisSerializationContext.RedisSerializationContextBuilder生成器=RedisSerializationContext
.newSerializationContext(新的StringRedisSerializer());
RedisSerializationContext=builder.key(serializer).value(serializer1.build();
;
返回新的反应器模板(
reactiveDisconnectionFactory,上下文);
}
}
这是我的查找服务类,它在请求过程中实际与redis通信
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ReactiveRedisOperations;
import org.springframework.stereotype.Service;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.RedisRepo;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxDetails;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxLine;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.util.JsonUtil;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Service
public class RedisTaxLineLookUpService {
private static final Logger log = LoggerFactory.getLogger(RedisTaxLineLookUpService.class);
@Autowired
private ReactiveRedisOperations<TaxDetails, TaxLine> redisOperations;
public Flux<TaxLine> get(TaxDetails taxDetails) {
log.info("going to call redis to fetch tax lines{}", JsonUtil.toJsonString(taxDetails));
return redisOperations.keys(taxDetails).flatMap(redisOperations.opsForValue()::get);
}
public Mono<RedisRepo> set(RedisRepo redisRepo) {
log.info("going to call redis to save tax lines{}", JsonUtil.toJsonString(redisRepo.getTaxDetails()));
return redisOperations.opsForValue().set(redisRepo.getTaxDetails(), redisRepo.getTaxLine())
.map(__ -> redisRepo);
}
}
导入org.slf4j.Logger;
导入org.slf4j.LoggerFactory;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.data.redis.core.ReactiveRedisOperations;
导入org.springframework.stereotype.Service;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.RedisRepo;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxDetails;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxLine;
导入com.sap.slh.tax.attributes.determination.springwebfluxdemo.util.JsonUtil;
导入reactor.core.publisher.Flux;
导入reactor.core.publisher.Mono;
@服务
公共类RedisteLineLookupService{
私有静态最终记录器log=LoggerFactory.getLogger(RedisTaxLineLookUpService.class);
@自动连线
私有反应器操作和再操作;
公共流量获取(TaxDetails TaxDetails){
log.info(“将调用redis获取税务行{}”,JsonUtil.toJsonString(taxDetails));
返回redisOperations.keys(taxDetails).flatMap(redisOperations.opsForValue()::get);
}
公共单声道集(RedisRepo RedisRepo){
log.info(“将调用redis来保存税行{}”,JsonUtil.toJsonString(redisRepo.getTaxDetails());
返回redisOperations.optsfervalue().set(redisRepo.getTaxDetails(),redisRepo.getTaxLine())
.map(_uu->redisRepo);
}
}
堆栈跟踪:
2020-03-26T16:27:54.513+0000[APP/PROC/WEB/0]OUT org.springframework.data.redis.RedisConnectionFailureException:无法连接到redis;嵌套异常为io.莴苣.core.RedisConnectionException:无法连接到org.springframework.data.redis.connection.莴苣.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1199)上的10.11.241.101:36516|抑制:reactor.core.publisher.FluxOnAssembly$OnAssemblyException:|在以下站点观察到错误:| | |检查点?Handler com.sap.slh.tax.attributes.determination.springwebfluxdemo.controller.TaxLinesDeterminationController#saveTaxLines(RedisRepo)[DispatcherHandler]| | | |检查点?HTTP://POST/tax/l
import java.time.Duration;
import java.util.List;
import java.util.stream.Collectors;
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.RedisConfiguration;
import org.springframework.data.redis.connection.RedisNode;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
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.core.ReactiveRedisOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxDetails;
import com.sap.slh.tax.attributes.determination.springwebfluxdemo.model.TaxLine;
import io.lettuce.core.RedisURI;
import io.pivotal.cfenv.core.CfEnv;
@Configuration
public class RedisConfig {
CfEnv cfEnv = new CfEnv();
String tag = "redis";
String redisHost = cfEnv.findCredentialsByTag(tag).getHost();
@Bean
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory(RedisConfiguration defaultRedisConfig) {
LettuceClientConfiguration clientConfig = LettucePoolingClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(60000)).build();
return new LettuceConnectionFactory(defaultRedisConfig, clientConfig);
}
@Bean
public RedisConfiguration defaultRedisConfig() {
if (redisHost != null) {
// RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("127.0.0.1", 6379);
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
String redisPort = cfEnv.findCredentialsByTag(tag).getPort();
String redisPassword = cfEnv.findCredentialsByTag(tag).getPassword();
config.setHostName(redisHost);
config.setPassword(RedisPassword.of(redisPassword));
config.setPort(Integer.parseInt(redisPort));
config.setDatabase(2);
return config;
} else {
RedisSentinelConfiguration config = new RedisSentinelConfiguration();
String uri = cfEnv.findCredentialsByTag(tag).getUri();
RedisURI redisURI = RedisURI.create(uri);
config.master(redisURI.getSentinelMasterId());
List<RedisNode> nodes = redisURI.getSentinels().stream()
.map(redisUri -> populateNode(redisUri.getHost(), redisUri.getPort())).collect(Collectors.toList());
nodes.forEach(node -> config.addSentinel(node));
config.setPassword(RedisPassword.of(redisURI.getPassword()));
config.setDatabase(2);
return config;
}
}
@Bean
public ReactiveRedisOperations<TaxDetails, TaxLine> reactiveRedisTemplate(
ReactiveRedisConnectionFactory factory) {
StringRedisSerializer keySerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer<TaxLine> valueSerializer = new Jackson2JsonRedisSerializer<>(
TaxLine.class);
Jackson2JsonRedisSerializer<TaxDetails> valueSerializer1 = new Jackson2JsonRedisSerializer<>(
TaxDetails.class);
RedisSerializationContext.RedisSerializationContextBuilder<TaxDetails, TaxLine> builder = RedisSerializationContext
.newSerializationContext(keySerializer);
RedisSerializationContext<TaxDetails, TaxLine> context = builder.key(valueSerializer1).value(valueSerializer).build();
return new ReactiveRedisTemplate<>(factory, context);
}
private RedisNode populateNode(String host, Integer port) {
return new RedisNode(host, port);
}
}
<groupId>io.pivotal.cfenv</groupId>
<artifactId>java-cfenv-boot</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
@Configuration
@ConfigurationProperties(prefix = "spring.redis")
@Setter
public class RedisConfig {
private String host;
private String password;
@Bean
@Primary
public ReactiveRedisConnectionFactory reactiveRedisConnectionFactory(RedisConfiguration defaultRedisConfig) {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.useSsl().build();
return new LettuceConnectionFactory(defaultRedisConfig, clientConfig);
}
@Bean
public RedisConfiguration defaultRedisConfig() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
config.setHostName(host);
config.setPassword(RedisPassword.of(password));
return config;
}
}