1、首先查看docker的內存占用情況:
docker top 容器名 -u 查看內存cpu占用率(容器名來自kubectl describe pod xxx或者docker ps)
可以看出內存一直增長,作為IO代理這是不正常的。
2、修改啟動參數和配置文件
需要注意的是為了安全考慮,docker默認是不能使用一些調試手段的,需要修改啟動參數和yaml
docker file中增加啟動參數(yaml中應該也可以):
ENTRYPOINT ["java", "-jar", "/usr/local/bin/access-1.0-SNAPSHOT.jar", "-XX:NativeMemoryTracking=detail"]
yaml增加:
apiVersion: apps/v1
kind: Deployment
.......
spec:........template:........spec: containers:- name: access......... securityContext:capabilities:add: ["SYS_PTRACE"]
3、查看具體內存占用
各類內存增長情況:
#建立內存基線
jcmd 1 VM.native_memory baseline
#與基線對比
jcmd 1 VM.native_memory summary.diff
其中1是pid,可以通過jps查看
查看當前內存具體申請源:
jcmd 1 VM.native_memory detail scale=MB
查看結果是Other的內存增長比較明顯:
[0x00007f76b2143b77] Unsafe_AllocateMemory0+0x87
[0x00007f769577c4ba](malloc=732MB type=Other #228)
Unsafe_AllocateMemory0一般是ByteBuf申請的內存,jvm不管理,也就是不會gc,需要自己關注申請和釋放
4、自己申請的ByteBuf
自己申請的ByteBuf要么往下傳遞(通過ctx write或者fire read)由后面的pipe節點釋放,要么自己通過release釋放。
如果是寫入服務器response中的content,通過ctx.writeAndFlush往下傳遞,由netty去管就行了。
5、在pipe的handle中收到的msg
比如服務器上收到的request,如果不是最后一個節點,則必須顯式傳遞:ctx.fireChannelRead(msg);
如果是最后一個節點則自己手動釋放,可以content.release也可以ReferenceCountUtil.release(msg);
也可以繼承SimpleChannelInboundHandler,SimpleChannelInboundHandler中會釋放,不用自己釋放了。
如果是服務器處理一個請求回復一個響應,一般是作為最后一個節點,可以繼承SimpleChannelInboundHandler。