相关文章推荐
任性的野马  ·  BAEKHYUN JAPAN ...·  2 月前    · 
怕老婆的大熊猫  ·  Setting up OctoPrint ...·  1 年前    · 
谦虚好学的烤红薯  ·  Android Studio ...·  1 年前    · 
腼腆的柑橘  ·  记:curl ...·  1 年前    · 
淡定的米饭  ·  锈湖根源剧情解析 ...·  1 年前    · 
  • Home
  • Water Cooler
  • Beta
  • Flings
  • Education
  • Members
  • My SpringBoot app is connecting to a Redis sharded cluster in Azure for better scalability.

    Using Jedis to set up the connection and the RedisClusterConfiguration class, my app is unable to perform

    Redis any commands: redis.clients.jedis.exceptions.JedisMovedDataException: MOVED

    If Jedis is not proper framework for a sharded Redis cluster, what is the alternative framework and where could I find a reference implementation?

    My config class:

    @Bean

    public RedisConnectionFactory connectionFactory() {

    return new JedisConnectionFactory(getClusterConfiguration());

    }

    @Bean

    public RedisClusterConfiguration getClusterConfiguration() {

    Map<String, Object> source = Maps. newHashMap ();

    source.put("spring.redis.cluster.nodes", "xxxx.redis.cache.windows.net:6380");

    source.put("spring.redis.cluster.timeout", "30");

    source.put("spring.redis.cluster.password", "xxxxxx");

    return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));

    }

    yeah, but Azure does not give me access to the underlying nodes . Azure Redis has a load balancer in front of the sharded cluster.

    This does not work either:

    @Bean

    public RedisConnectionFactory connectionFactory() {

    JedisConnectionFactory conn = new JedisConnectionFactory();

    conn.setHostName("ds1-redic-poc.redis.cache.windows.net");

    conn.setPassword("GfZ417sFRDlMBR7yqsO0611oaEN5L6SiANjQujoz7WE=");

    conn.setPort(6380);

    conn.setUseSsl(true);

    conn.setUsePool(true);

    conn.setTimeout(socketTO);

    JedisPoolConfig config = new JedisPoolConfig();

    config.setMaxIdle(maxIdle);

    config.setMaxTotal(maxTotal);

    config.setMinIdle(minIdle);

    config.setMaxWaitMillis(maxWaitMillis);

    config.setBlockWhenExhausted(blockWhenExhausted);

    conn.setPoolConfig(config);

    return conn;

    }

    Does Springboot support lettuce?

    >Does Springboot support lettuce?

    Yes. It looks like it should be the default, according to this. At least in 2.0 + 2.1.

    https://docs.spring.io/spring-boot/docs/2.1.2.RELEASE/reference/htmlsingle/#boot-features-redis

    If it's not being picked up check and see if you have Jedis being pulled in somewhere and maybe try excluding the dependency. Also, make sure Lettuce is being pulled in as a dependency and not excluded. If it's on the class path it should use Lettuce.

    Daniel - Managing the library dependencies is not as smooth as that. A full reference iplementation/sample project would be very helpful.

    org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.RedisConnectionFactory]: Factory method 'connectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: com/lambdaworks/redis/RedisException

    --- gradle build ----

    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'

    compile group: 'com.lambdaworks', name: 'lettuce' , version: '2.3.3'

    compile group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE'

    compile 'redis.clients:jedis'

    --- config class --

    @Bean

    public PdfLocationRepositoryCustom pdfLocationRepositoryImpl(){

    return new PdfLocationRedisRepositoryImpl(redisTemplate());

    }

    @Bean

    public RedisConnectionFactory connectionFactory() {

    return new LettuceConnectionFactory(getRedisClusterConfiguration());

    //return new JedisConnectionFactory(getRedisClusterConfiguration());

    }

    @Bean

    public RedisClusterConfiguration getRedisClusterConfiguration() {

    Map<String, Object> source = Maps. newHashMap ();

    source.put("spring.redis.cluster.nodes", "ds1-redic-poc.redis.cache.windows.net:6380");

    source.put("spring.redis.cluster.timeout", "30");

    //source.put("spring.redis.cluster.max", ?);

    source.put("spring.redis.cluster.password", "xxxxxx");

    //source.put("spring.redis.cluster.max-redirects", ?);

    return new RedisClusterConfiguration(new MapPropertySource("RedisClusterConfiguration", source));

    }

    @Bean

    public RedisTemplate<String, Object> redisTemplate() {

    RedisTemplate<String, Object> template = new RedisTemplate<>();

    template.setConnectionFactory(connectionFactory());

    template.setKeySerializer(new StringRedisSerializer());

    template.setHashValueSerializer(new GenericToStringSerializer<>( Object.class ));

    return template;

    }

    With all these libs checked in gradle:

    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis'

    //compile group: 'org.apache.commons', name: 'commons-pool2'

    compile group: 'com.lambdaworks', name: 'lettuce' , version: '2.3.3'

    compile group: 'biz.paluch.redis', name: 'lettuce', version: '4.0.Final'

    compile group: 'io.lettuce', name: 'lettuce-core', version: '5.0.0.RELEASE'

    compile 'org.springframework.data:spring-data-redis'

    compile 'redis.clients:jedis'

    Hmm, it seems like there could be multiple things that cause this. I did find this Github issue which seems to indicate that Lettuce 4.2+ supports Azure Redis Clusters. If you're on 4.5 like in my demo app that should be good enough.

    https://github.com/lettuce-io/lettuce-core/issues/246

    You might need to hunt for more clues as to what's failing. Maybe try turning up the log level for `org.springframework.data` and/or Lettuce (not sure the package name off hand). Similarly, you might try `tcpdump` or Wireshark to capture the traffic and dig in more, although that's challenging if TLS is involved.

    Aside from that Pivotal doesn't support Lettuce itself, so if there is a core issue with it, I would suggest opening a Github issue. The author seems quite active.

    Hope that helps!

    Finally getting my app with Lettuce running in PCF / Azure.

    Facing now a new issue and investigating:

    Caused by: org.springframework.data.redis.RedisSystemException: Redis exception; nested exception is com.lambdaworks.redis.RedisException: Cannot retrieve initial cluster partitions from initial URIs [RedisURI [host='ds1-redic-poc.redis.cache.windows.net', port=6380]]

    Ok - I got it to connect now. Needed to set SSL to true. Getting a strange memory exception now:

    com.lambdaworks.redis.RedisException: io.netty.handler.codec.EncoderException: io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16776960 byte(s) of direct memory (used: 66816, max: 10485760)

    OK, looks like it's using Direct Memory. The Java buildpack defaults the max direct memory to 10M. It looks like you will need more than that. You can bump that up and it should help. See the two sections here.

    https://github.com/cloudfoundry/java-buildpack/blob/master/docs/jre-open_jdk_jre.md#java-options

    From what I read earlier, it didn't seem like there was a standard in terms of how servers are configured. It could be something MS is doing in their implementation that's just not compatible with the clients. Java is a big space though so you'd think they could provide one Java Redis client that works. Jedis & Lettuce are two popular clients, so if neither works, it sounds like it's time to check with Microsoft Support & see what they have to say.

    Post back if you're able to work out a solution or have more questions. Happy to help where we can from the Pivotal side.

    Dan

    Bad news. I am back to square one . Now that I have Lettuce connecting to an Azure Redis cache with 2 shards, I am getting the same exception I was getting with the other framework, Jedis:

    org.springframework.data.redis.RedisSystemException: Error in execution; nested exception is com.lambdaworks.redis.RedisCommandExecutionException: MOVED 13292 52.167.224.109:15003

    If I connect my app to an Azure Redis cache with 1 shard, I am able to run different CRUD operations against it. (I also tried to use the non SSL port and that did not help. )

    It is very disappointing as I followed Microsoft's recommended solution to use Lettuce.

    A tutorial like this one (https://docs.microsoft.com/en-us/java/azure/spring-framework/configure-spring-boot-initializer-java-app-with-redis-cache?view=azure-java-stable) is helpful for a simple initial deployment but is not enough to demonstrate how Azure cache can support an Elastic Cache solution when

    Azure does not provide a mechanism to access the underlying Redis nodes that seemed to be needed by these frameworks. (https://github.com/lettuce-io/lettuce-core/blob/5.1.3.RELEASE/src/test/java/io/lettuce/examples/ConnectToMasterSlaveUsingElastiCacheCluster.java)

    THoughts?

    Unless Microsoft is able to demonstrate with a reference implementation that we can use the Elastic Cache, we are going to have to look at the alternative approach with Redis Lab on our side.

    Any others thoughts on your side?

    Dan

    Do you know if there is a way to configure the LettuceConnection with both a cluster and a pool object?

    LettuceConnectionFactory clientConfig = new LettuceConnectionFactory(lettucePool); // DefaultLettucePool

    LettuceConnectionFactory factory = new LettuceConnectionFactory(clusterConfig); //RedisClusterConfiguration

    Dear All,

    I appreciate if you could provide if you could get Jedis or Lettuce working with Azure Redis cache service in Pivotal Cloud Foundry to create pooling configuration. Please advice if Jedis/Lettuce is supported in PCF ?

    I am using following configuration:

    private JedisPoolConfig buildPoolConfig() {

    final JedisPoolConfig poolConfig = new JedisPoolConfig();

    poolConfig.setMaxTotal(20);

    poolConfig.setMaxIdle(20);

    poolConfig.setMinIdle(5);

    poolConfig.setTestOnBorrow(true);

    poolConfig.setTestOnReturn(true);

    poolConfig.setTestWhileIdle(true);

    poolConfig.setMinEvictableIdleTimeMillis(Duration.ofSeconds(20).toMillis());

    poolConfig.setTimeBetweenEvictionRunsMillis(Duration.ofSeconds(20).toMillis());

    poolConfig.setNumTestsPerEvictionRun(-1);

    poolConfig.setBlockWhenExhausted(true);

    return poolConfig;

    Also using in the application.yml:

    redis:

    jedis:

    pool:

    max-active: 3

    max-idle: 3

    max-wait: 1

    min-idle: 1

    timeout: 3000

    Thanks in advance.

    Best Regards,

    OP

    @Oscar P - There is nothing specific to PCF in how you configure a Jedis/Lettuce connection pool. It is the same process on PCF as on your laptop or on a server/VM. The only difference is that you may choose to use different values for development on your local machine vs production on PCF.

    https://docs.spring.io/spring-boot/docs/2.2.x/reference/html/spring-boot-features.html#boot-features-redis

    See also all the properties you can set to configure things (Find in Page "redis" on the link below):

    https://docs.spring.io/spring-boot/docs/2.2.x/reference/html/appendix-application-properties.html#data-properties

    In addition, you can choose to get Redis configuration from a bound service. That is typically only for things like host, port and creds. Your pool configuration would not typically come from the bound service.

    As an FYI, if you want to pull bound service info, you can use https://github.com/pivotal-cf/java-cfenv. That's the recommended approach.

    Hope that helps!

    PS. Please start a new thread if you have more questions.

  • Terms of Use
  •