Sid*_*ohn 7 multithreading asynchronous redis lettuce spring-data-redis
我们使用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. 计算出的实际可用内存为 4GBMaxDirectMemorySize可能有点保守。这可能是问题的一部分。
问题的潜在解决方案
MaxDirectMemorySizeJVM --> 但我们不确定这是否足够Netty不使用DirectMemory( noPreferDirect=true) -->Netty然后将使用堆,但是如果这会减慢我们的应用程序的速度太多,如果Netty内存太少,我们是不安全的Lettuce为shareNativeConnection=false--> 这会导致与 redis 的多个连接我们的问题是:我们如何以正确的方式解决这个问题?
我很乐意提供有关如何设置应用程序配置的更多信息(application.yml、LettuceConnection 等),如果其中任何一个有助于解决问题。
感谢https://gitter.im/lettuce-io/Lobby的人们,我们得到了一些关于如何解决这些问题的线索。
正如怀疑的那样,考虑到总可用内存,10MMaxDirectMemorySize过于保守。
建议增加该值。由于我们实际上并不知道需要多少内存Netty才能更稳定地运行,因此我们考虑了以下步骤。
第一:我们将通过设置禁用Netty偏好设置。然后将使用堆缓冲区。MaxDirectMemorynoPreferDirect=trueNetty
第二:Netty然后我们将监视操作期间将消耗多少堆内存。这样做,我们将能够推断出 的平均内存消耗Netty。
第三:我们将获取平均内存消耗值,并MaxDirectMemorySize通过在 JVM 选项中将其设置为“新” -XX:MaxDirectMemorySize。然后我们将重新启用通过设置Netty来使用。DirectMemorynoPreferDirect=false
第四:监视日志条目和异常,看看我们是否仍然有问题,或者这是否有效。
[更新]
我们从上述步骤开始,但意识到该设置noPreferDirect=true并不能完全阻止 netty 使用 DirectMemory。对于某些用例(nio-Processes)Netty仍然使用 DirectMemory。
所以我们必须增加MaxDirectMemorySize.
现在我们设置以下 JAVA_OPTS -Dio.netty.noPreferDirect=true -XX:MaxDirectMemorySize=100M。这可能会解决我们的问题。
| 归档时间: |
|
| 查看次数: |
6375 次 |
| 最近记录: |