OpenFeign / feign

Feign makes writing java http clients easier
Apache License 2.0
9.51k stars 1.93k forks source link

Deadlock when using feign in @PostConstruct with CompletableFuture #2544

Open jinkshower opened 2 months ago

jinkshower commented 2 months ago
"ForkJoinPool.commonPool-worker-1" #39 daemon prio=5 os_prio=31 cpu=2.77ms elapsed=14.76s tid=0x000000015e4a4600 nid=0x8c0b waiting for monitor entry  [0x0000000170441000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:217)
        - waiting to lock <0x0000000700dfab40> (a java.util.concurrent.ConcurrentHashMap)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:275)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getObject(DefaultListableBeanFactory.java:2070)
        at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:66)
        at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
        at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
        at feign.InvocationContext.decode(InvocationContext.java:114)
        at feign.InvocationContext.proceed(InvocationContext.java:88)
        at feign.ResponseInterceptor$Chain$$Lambda$1184/0x000000b001941a48.next(Unknown Source)
        at feign.ResponseHandler.handleResponse(ResponseHandler.java:63)
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114)
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70)
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99)
        at jdk.proxy2.$Proxy159.fetch(jdk.proxy2/Unknown Source)
        at hiyen.galmanhae.dataprocess.application.CongestionService.fetch(CongestionService.java:22)
        at hiyen.galmanhae.dataprocess.DataProcessor.aggregatePlace(DataProcessor.java:61)
        at hiyen.galmanhae.dataprocess.DataProcessor.lambda$toFuture$0(DataProcessor.java:50)
        at hiyen.galmanhae.dataprocess.DataProcessor$$Lambda$1520/0x000000b001b86a68.get(Unknown Source)
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(java.base@17.0.12/CompletableFuture.java:1768)
        at java.util.concurrent.CompletableFuture$AsyncSupply.exec(java.base@17.0.12/CompletableFuture.java:1760)
        at java.util.concurrent.ForkJoinTask.doExec(java.base@17.0.12/ForkJoinTask.java:373)
        at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(java.base@17.0.12/ForkJoinPool.java:1182)
        at java.util.concurrent.ForkJoinPool.scan(java.base@17.0.12/ForkJoinPool.java:1655)
        at java.util.concurrent.ForkJoinPool.runWorker(java.base@17.0.12/ForkJoinPool.java:1622)
        at java.util.concurrent.ForkJoinWorkerThread.run(java.base@17.0.12/ForkJoinWorkerThread.java:165)

"ForkJoinPool.commonPool-worker-2" #40 daemon prio=5 os_prio=31 cpu=3.25ms elapsed=14.76s tid=0x000000015e4a4c00 nid=0x9e1b waiting for monitor entry  [0x000000017064d000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:217)
        - waiting to lock <0x0000000700dfab40> (a java.util.concurrent.ConcurrentHashMap)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:275)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectProvider.getObject(DefaultListableBeanFactory.java:2070)
        at org.springframework.cloud.openfeign.support.SpringDecoder.decode(SpringDecoder.java:66)
        at org.springframework.cloud.openfeign.support.ResponseEntityDecoder.decode(ResponseEntityDecoder.java:62)
        at feign.optionals.OptionalDecoder.decode(OptionalDecoder.java:36)
        at feign.InvocationContext.decode(InvocationContext.java:114)
        at feign.InvocationContext.proceed(InvocationContext.java:88)
        at feign.ResponseInterceptor$Chain$$Lambda$1184/0x000000b001941a48.next(Unknown Source)
        at feign.ResponseHandler.handleResponse(ResponseHandler.java:63)
        at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:114)
        at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70)
        at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99)
        at jdk.proxy2.$Proxy159.fetch(jdk.proxy2/Unknown Source)
        at hiyen.galmanhae.dataprocess.application.CongestionService.fetch(CongestionService.java:22)
        at hiyen.galmanhae.dataprocess.DataProcessor.aggregatePlace(DataProcessor.java:61)
        at hiyen.galmanhae.dataprocess.DataProcessor.lambda$toFuture$0(DataProcessor.java:50)
        at hiyen.galmanhae.dataprocess.DataProcessor$$Lambda$1520/0x000000b001b86a68.get(Unknown Source)
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(java.base@17.0.12/CompletableFuture.java:1768)
        at java.util.concurrent.CompletableFuture$AsyncSupply.exec(java.base@17.0.12/CompletableFuture.java:1760)
        at java.util.concurrent.ForkJoinTask.doExec(java.base@17.0.12/ForkJoinTask.java:373)
        at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(java.base@17.0.12/ForkJoinPool.java:1182)
        at java.util.concurrent.ForkJoinPool.scan(java.base@17.0.12/ForkJoinPool.java:1655)
        at java.util.concurrent.ForkJoinPool.runWorker(java.base@17.0.12/ForkJoinPool.java:1622)
        at java.util.concurrent.ForkJoinWorkerThread.run(java.base@17.0.12/ForkJoinWorkerThread.java:165)

I have no problem when using feignclient in @PostConstruct but when I use it with CompletableFuture, I get above deadlock

kdavisk6 commented 2 months ago

I'm not sure this is a Feign issue directly, but I'm going to make a guess that you are trying to initialize a FeignClient in a thread. Feign Client initialization is not thread safe, but an initialized Feign Client should be thread safe.

Looking at the stack trace, there appears to be dependency injection occurring as part of the decode operation. It's in that operation where the deadlock occurs. If you can provide a minimal reproducible example, we may be able to help track it down.