netty-grpc一次DirectByteBuffer内存泄露问题

 更新时间:2023年12月28日 08:47:04   作者:xihuanyuye  
这篇文章主要介绍了netty-grpc一次DirectByteBuffer内存泄露问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

应用场景

当前应用会采用grpc大量发送数据,并且并发量并不固定

报错日志

2022-10-31 22:20:51.630  INFO 8 --- [ueue4-thread-20] c.t.s.d.p.ParquetNoBlockDataReaderWriter : groupCount:1,count:300000,end read end read
2022-10-31 22:20:51.630  INFO 8 --- [ueue4-thread-20] c.t.privpy.sdk.task.data.DataSender      : MTU4NzA4NzE3MDkxNTUzNjg5Nw noFragment read data plain://ds02/xgboost_vertical-20221031221952-df1650ce/bins_Bob_13_0_tree0_depth0.parquet;type=int32 finished!
Exception in thread "send1-thread-7" 2022-10-31 22:20:51.634  INFO 8 --- [Queue3-thread-1] c.t.p.s.t.d.n.NoFragmentDataSender       : MTU4NzA4NzE3MDkxNTUzNjg5Nw read plain data plain://ds02/xgboost_vertical-20221031221952-df1650ce/bins_Bob_13_0_tree0_depth0.parquet;type=int32 success!
Exception in thread "NoFragRec7-thread-8" 2022-10-31 22:20:51.634  INFO 8 --- [ptor2-thread-10] c.t.p.s.t.d.n.NoFragmentDataSender       : MTU4NzA4NzE3MDkxNTUzNjg5Nw start cipher for plain data transfer plain://ds02/xgboost_vertical-20221031221952-df1650ce/bins_Bob_13_0_tree0_depth0.parquet;type=int32
io.grpc.netty.shaded.io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 1256 byte(s) of direct memory (used: 68121888, max: 67108864)
        at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.incrementMemoryCounter(PlatformDependent.java:754)
        at io.grpc.netty.shaded.io.netty.util.internal.PlatformDependent.allocateDirectNoCleaner(PlatformDependent.java:709)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledUnsafeNoCleanerDirectByteBuf.allocateDirect(UnpooledUnsafeNoCleanerDirectByteBuf.java:30)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf.allocateDirect(UnpooledByteBufAllocator.java:186)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledDirectByteBuf.<init>(UnpooledDirectByteBuf.java:64)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledUnsafeDirectByteBuf.<init>(UnpooledUnsafeDirectByteBuf.java:41)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledUnsafeNoCleanerDirectByteBuf.<init>(UnpooledUnsafeNoCleanerDirectByteBuf.java:25)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeNoCleanerDirectByteBuf.<init>(UnpooledByteBufAllocator.java:181)
        at io.grpc.netty.shaded.io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:91)
        at io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
        at io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:178)
        at io.grpc.netty.shaded.io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:115)
        at io.grpc.netty.shaded.io.netty.handler.codec.base64.Base64.encode(Base64.java:108)
        at io.grpc.netty.shaded.io.netty.handler.ssl.SslUtils.toBase64(SslUtils.java:375)
        at io.grpc.netty.shaded.io.netty.handler.ssl.PemX509Certificate.append(PemX509Certificate.java:128)
        at io.grpc.netty.shaded.io.netty.handler.ssl.PemX509Certificate.toPEM(PemX509Certificate.java:86)
        at io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslKeyMaterialProvider.validateSupported(OpenSslKeyMaterialProvider.java:78)
        at io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslKeyMaterialProvider.validateKeyMaterialSupported(OpenSslKeyMaterialProvider.java:44)
        at io.grpc.netty.shaded.io.netty.handler.ssl.OpenSslClientContext.<init>(OpenSslClientContext.java:193)
        at io.grpc.netty.shaded.io.netty.handler.ssl.SslContext.newClientContextInternal(SslContext.java:827)
        at io.grpc.netty.shaded.io.netty.handler.ssl.SslContextBuilder.build(SslContextBuilder.java:576)
        at com.tsingj.privpy.sdk.client.grpc.ChannelPool.getESManagedChannel(ChannelPool.java:211)
        at com.tsingj.privpy.sdk.client.grpc.EsClient.getNewChannel(EsClient.java:60)
        at com.tsingj.privpy.sdk.client.grpc.EsClient.getResultData(EsClient.java:289)
        at com.tsingj.privpy.sdk.task.data.nofragment.NoFragmentDataReceiver.lambda$new$2(NoFragmentDataReceiver.java:205)
        at com.tsingj.privpy.sdk.task.core.QueueWithConsumer.lambda$new$0(QueueWithConsumer.java:41)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:750)
Exception in thread "send1-thread-5" Exception in thread "send1-thread-1" io.grpc.netty.shaded.io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 4096 byte(s) of direct memory (used: 68121888, max: 67108864)

分析

计算了一下,大概是64M,正好是jvm启动时设置的参数大小。

java -server -Xms$XMS_VALUE -Xmx$XMX_VALUE -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseG1GC -Djava.rmi.server.hostname=localhost -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.rmi.port=8890 -Dcom.sun.management.jmxremote.port=8890 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError -XX:+UnlockExperimentalVMOptions -XX:G1MaxNewSizePercent=40 -XX:MaxDirectMemorySize=64M -XX:HeapDumpPath=/opt/gemini/javadsheapdump$DS_ID$DS_INSTANCE_ID -Xloggc:/opt/gemini/javadsgclog$DS_ID$DS_INSTANCE_ID -jar /ds/ds_run.jar --logging.level.root=$LOG_LEVEL

visualVm安装插件

观察到,其中buffer Pools稳定在40M+,重启后恢复。

当前怀疑在发送突然超过DirectByteBuffer总大小时,发生了Om,并且会导致后续一直无法回收内存。

当前策略

增大XX:MaxDirectMemorySize为512M,进行观察。

-XX:MaxDirectMemorySize=512M

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 关于SpringGateway调用服务 接受不到参数问题

    关于SpringGateway调用服务 接受不到参数问题

    这篇文章主要介绍了关于SpringGateway调用服务接受不到参数问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • springMVC的生命周期详解

    springMVC的生命周期详解

    本篇文章主要介绍了springMVC的生命周期详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Java8的DateTimeFormatter与SimpleDateFormat的区别详解

    Java8的DateTimeFormatter与SimpleDateFormat的区别详解

    这篇文章主要介绍了Java8的DateTimeFormatter与SimpleDateFormat的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • maven资源过滤打包后文件变大的处理方法

    maven资源过滤打包后文件变大的处理方法

    maven目前在web上面的使用方式很普遍,而打包的方式也存在很多方式,下面这篇文章主要给大家介绍了关于maven资源过滤打包后文件变大的处理方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-07-07
  • Java注解方式之防止重复请求

    Java注解方式之防止重复请求

    这篇文章主要介绍了关于Java注解方式防止重复请求,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • Java 并发编程创建线程的四种方式示例详解

    Java 并发编程创建线程的四种方式示例详解

    本文对比Java创建线程的四种方式:继承Thread类(单继承限制)、实现Runnable接口(灵活推荐)、实现Callable接口(支持返回值)、使用线程池(最佳实践,资源管理高效),推荐优先使用线程池提升系统稳定性与资源利用率,感兴趣的朋友一起看看吧
    2025-09-09
  • InputStreamReader和BufferedReader用法及实例讲解

    InputStreamReader和BufferedReader用法及实例讲解

    这篇文章主要介绍了InputStreamReader和BufferedReader用法及实例讲解的相关资料,需要的朋友可以参考下
    2015-12-12
  • java中File转为MultipartFile的四种实现方式

    java中File转为MultipartFile的四种实现方式

    这篇文章主要介绍了java中File转为MultipartFile的四种实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • 一次因Java应用造成CPU过高的排查实践过程

    一次因Java应用造成CPU过高的排查实践过程

    一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环。下面这篇文章主要给大家介绍了一次因Java应用造成CPU过高的排查实践过程,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-11-11
  • java在文件尾部追加内容的简单实例

    java在文件尾部追加内容的简单实例

    下面小编就为大家带来一篇java在文件尾部追加内容的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12

最新评论