【问题标题】:Resource leak detected when using spring-data-redis on cloud foundry在 Cloud Foundry 上使用 spring-data-redis 时检测到资源泄漏
【发布时间】:2019-04-16 14:14:56
【问题描述】:

我们开发了一个spring-boot服务,它提供了一个rest api(spring-webflux)并通过RabbitMQ(spring-rabbit)发送数据。该服务部署在 Cloud Foundry 上,我们在 2.1.4 版本中使用 spring-boot。我们添加了 spring-boot-starter-data-redis 来使用 redis 缓存一些数据,我们得到了以下错误:

[io.netty.util.ResourceLeakDetector] [] LEAK: HashedWheelTimer.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 
Created at:
    io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:284)
    io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:217)
    io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:196)
    io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:178)
    io.netty.util.HashedWheelTimer.<init>(HashedWheelTimer.java:162)
    io.lettuce.core.resource.DefaultClientResources.<init>(DefaultClientResources.java:169)
    io.lettuce.core.resource.DefaultClientResources$Builder.build(DefaultClientResources.java:532)
    io.lettuce.core.resource.DefaultClientResources.create(DefaultClientResources.java:233)
    io.lettuce.core.AbstractRedisClient.<init>(AbstractRedisClient.java:98)
    io.lettuce.core.RedisClient.<init>(RedisClient.java:87)
    io.lettuce.core.RedisClient.create(RedisClient.java:124)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.lambda$createClient$7(LettuceConnectionFactory.java:971)
    java.base/java.util.Optional.orElseGet(Unknown Source)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.createClient(LettuceConnectionFactory.java:971)
    org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:273)
    org.springframework.cloud.service.keyval.RedisConnectionFactoryCreator.create(RedisConnectionFactoryCreator.java:88)
    org.springframework.cloud.service.keyval.RedisConnectionFactoryCreator.create(RedisConnectionFactoryCreator.java:31)
    org.springframework.cloud.Cloud.getServiceConnector(Cloud.java:288)
    org.springframework.cloud.Cloud.getSingletonServiceConnector(Cloud.java:202)
    org.springframework.cloud.config.java.CloudServiceConnectionFactory.redisConnectionFactory(CloudServiceConnectionFactory.java:260)
    org.springframework.cloud.config.java.CloudServiceConnectionFactory.redisConnectionFactory(CloudServiceConnectionFactory.java:242)
    ...

这个错误只发生在我们在cloud Foundry上运行服务时,如果我们在本地运行它,我们不会收到任何错误。

我们这边不做连接工厂和stringRedisTemplate的任何配置,只使用spring-autoconfiguration配置的stringRedisTemplate。 我们对 Cloud Foundry 上的 Redis 使用以下配置:

@Configuration
@Profile( "cloud" )
public class CloudSpecificConfig extends AbstractCloudConfig {

   @Bean
   public RedisConnectionFactory redisConnectionFactory() {
      return connectionFactory().redisConnectionFactory();
   }
}

这就是我们使用模板的方式

@Component
@RequiredArgsConstructor
public final class RequestUtil {

   private final StringRedisTemplate myRedisTemplate;

   public String cacheId(String id, String value) {
      myRedisTemplate.opsForValue().set( id, value );

   }
}

这些是我们的 spring 依赖项:

<properties>
  <spring-boot-version>2.1.4.RELEASE</spring-boot-version>
</properties>

  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-webflux</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-configuration-processor</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-sleuth</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-cloud-connectors</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-amqp</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>
  <dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-data-redis</artifactId>
     <version>${spring-boot-version}</version>
  </dependency>

我们这边很困惑,因为我们这边没有做任何具体的配置。它看起来像云上的弹簧配置有问题。我们做错了什么吗?我们需要配置不同的东西吗?这是一个错误吗?

【问题讨论】:

  • 你解决了吗?

标签: spring spring-boot spring-cloud-config spring-data-redis lettuce


【解决方案1】:

这是我必须做的

我看看能不能找到更优雅的方式

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

@SuppressWarnings("unused")
@Bean
public RedisConnectionFactory redisConnectionFactory(DefaultClientResources dependency) {
    return connectionFactory().redisConnectionFactory("redis-pcf-service");
}

【讨论】:

    【解决方案2】:

    最终问题在我们这边消失了,因为我们将 redis 客户端从 lettuce 更改为 jedis。

    我们遇到了生菜问题,即我们会失去与云基础架构上的 redis 服务的连接。但是由于在我们换客户端的同时redis服务也有更新,所以不知道是不是和lettuce有关。

    也许在我们基于cloudfoundry的云结构上与redis服务结合的自动配置也有问题

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      • 1970-01-01
      • 1970-01-01
      • 2013-02-21
      • 1970-01-01
      相关资源
      最近更新 更多