我们使用spring-data-redis抽象spring-cache并lettuce作为我们的 redis 客户端。此外,我们在某些方法上使用多线程和异步执行。
示例工作流程如下所示:
Main-Method A(主线程)--> 调用 Method B ( @Async),这是一个代理方法,能够在另一个线程中异步运行逻辑。--> 方法 B 调用方法 C,即@Cacheable。注释@Cacheable处理对我们的 redis 缓存的读/写。
有什么问题?
Lettuceis Netty-based ,其工作依赖于DirectMemory. 由于@Async我们程序的性质,我们有多个线程同时使用LettuceConnection(因此)。Netty
Netty根据设计,所有线程都将使用共享DirectMemory. 由于明显太小,当访问的线程太多时,MaxDirectMemorySize我们会得到一个。OutOfDirectMemoryErrorNetty
例子:
io.lettuce.core.RedisException: io.netty.handler.codec.EncoderException: io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 8388352 byte(s) of direct memory (used: 4746467, max: 10485760)
到目前为止我们发现了什么?
我们使用https://docs.cloudfoundry.org/buildpacks/java/并MaxDirectMemorySize使用https://github.com/cloudfoundry/java-buildpack-memory-calculator进行计算。
这导致了MaxDirectMemorySize=10M. 计算出的实际可用内存为 4GB …