Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blockhound detects block call in DefaultConnectionFuture #1692

Closed
gustavosci opened this issue Mar 25, 2021 · 3 comments
Closed

Blockhound detects block call in DefaultConnectionFuture #1692

gustavosci opened this issue Mar 25, 2021 · 3 comments
Labels
for: external-project For an external project and not something we can fix

Comments

@gustavosci
Copy link

Bug Report

While testing we detected a blocking call in lettuce client, specifically in the class DefaultConnectionFuture.
How could we avoid this block call?

Lettuce version: 6.0.1.RELEASE

Stack trace: at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java) ~[na:na] at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:194) ~[na:na] at java.base/java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1796) ~[na:na] at java.base/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3128) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1823) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1998) ~[na:na] at io.lettuce.core.DefaultConnectionFuture.get(DefaultConnectionFuture.java:69) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:315) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:211) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1459) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1247) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1230) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedReactiveConnection(LettuceConnectionFactory.java:989) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:445) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getReactiveConnection(LettuceConnectionFactory.java:98) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.core.ReactiveRedisTemplate.lambda$doInConnection$0(ReactiveRedisTemplate.java:198) ~[spring-data-redis-2.4.1.jar:2.4.1]

Thanks in advance.

@mp911de mp911de added the for: external-project For an external project and not something we can fix label Mar 25, 2021
@mp911de
Copy link
Collaborator

mp911de commented Mar 25, 2021

That's a Spring Data Redis issue where you need to enable eager connection factory initialization.

@mp911de mp911de closed this as completed Mar 25, 2021
@gustavosci
Copy link
Author

Hey @mp911de, first of all, thanks for your answer.

I tried to use eager connection factory initialization, however now I'm getting the following error when trying to connect to redis during application startup:

Caused by: io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379 at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:78) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.RedisConnectionException.create(RedisConnectionException.java:56) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:320) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:211) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1459) ~[spring-data-redis-2.4.1.jar:2.4.1] ... 66 common frames omitted Caused by: io.netty.channel.StacklessClosedChannelException: null at io.netty.channel.AbstractChannel$AbstractUnsafe.ensureOpen(ChannelPromise)(Unknown Source) ~[netty-transport-4.1.54.Final.jar:4.1.54.Final]

After getting this, I also tried to change the related beans (ReactiveRedisConnectionFactory and ReactiveRedisTemplate) to be lazy, since my assumption is that at application startup the netty channels are not ready to be used yet. Well, the application started, but when I made the first operation with redis and the bean LettuceConnectionFactory was created, I got the same block call:

Caused by: reactor.blockhound.BlockingOperationError: Blocking call! jdk.internal.misc.Unsafe#park at java.base/jdk.internal.misc.Unsafe.park(Unsafe.java) ~[na:na] at java.base/java.util.concurrent.locks.LockSupport.park(LockSupport.java:194) ~[na:na] at java.base/java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1796) ~[na:na] at java.base/java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3128) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1823) ~[na:na] at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1998) ~[na:na] at io.lettuce.core.DefaultConnectionFuture.get(DefaultConnectionFuture.java:69) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.AbstractRedisClient.getConnection(AbstractRedisClient.java:315) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at io.lettuce.core.RedisClient.connect(RedisClient.java:211) ~[lettuce-core-6.0.1.RELEASE.jar:6.0.1.RELEASE] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.lambda$getConnection$1(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at java.base/java.util.Optional.orElseGet(Optional.java:369) ~[na:na] at org.springframework.data.redis.connection.lettuce.StandaloneConnectionProvider.getConnection(StandaloneConnectionProvider.java:115) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$ExceptionTranslatingConnectionProvider.getConnection(LettuceConnectionFactory.java:1459) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getNativeConnection(LettuceConnectionFactory.java:1247) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory$SharedConnection.getConnection(LettuceConnectionFactory.java:1230) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.getSharedConnection(LettuceConnectionFactory.java:979) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.initConnection(LettuceConnectionFactory.java:475) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory.afterPropertiesSet(LettuceConnectionFactory.java:297) ~[spring-data-redis-2.4.1.jar:2.4.1] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1847) ~[spring-beans-5.3.1.jar:5.3.1] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1784) ~[spring-beans-5.3.1.jar:5.3.1] ... 142 common frames omitted

My current simple config is:

    @Bean
    @Primary
    fun getReactiveRedisConnectionFactory() : ReactiveRedisConnectionFactory {
        val factory = LettuceConnectionFactory()
        factory.eagerInitialization = true
        return factory
    }

    @Bean
    fun getReactiveRedisTemplate(factory: ReactiveRedisConnectionFactory): ReactiveRedisTemplate<String, Order> {
        val keySerializer = StringRedisSerializer()
        val valueSerializer = Jackson2JsonRedisSerializer(Order::class.java)

        val builder = RedisSerializationContext.newSerializationContext<String, Order>(keySerializer)
        val context = builder.value(valueSerializer).build()

        return ReactiveRedisTemplate(factory, context)
    }

Am I missing something important here?

Thanks for your help!

@mp911de
Copy link
Collaborator

mp911de commented Mar 26, 2021

That is the natural consequence. Either you can initialize the connection at startup and move blocking calls onto the main thread or lazy initialization on the first access where blocking calls happen on the thread that requests the connection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

No branches or pull requests

2 participants