Nkn-tunnel 报错,Message channel full, discarding msg

Golang 里面 deadline 设置的是一个绝对的过期时间。比如你在创建 session 的时候设置了 deadline 是 1 分钟以后,那么无论这1分钟内发生了什么,1 分钟之后都算是 deadline 过期。如果为了保持 tcp 连接在正常使用时不报错,常用的做法是在每次读取(发送)成功的时候都重新延期 deadline。所以如果是在 DailWithConfig 或者其他创建 Session 的时候就设置了 deadline,那么你就需要保证在这个 deadline 的时间之前完成所有的正常读写操作,否则时间一到就报错了。

嗷嗷┗|`O′|┛ 嗷~~懂你的意思了。每次都会重新定义deadline。那确实要重写io.Copy(),每次读取发送成功后重新deadline。先生大才 :+1:

现在我加了读取超时机制,但是还会出现ReceiveWith函数里面的proto.Unmarshal占用内存

image 这个是发送端
image 这个是接收端

这个看起来似乎就是正常的收发的数据,被 protobuf 编解码以后占用的内存,还没有被 GC 给释放掉。现在的内存占用情况如何呢?还是存在一直往上涨的情况嘛?

还有一个可以测试的:增加 go GC 的运行频率,具体做法是设置 GOGC 环境变量,比如

GOGC=10 ./nkn-tunnel ...

这样运行可以让 GC 的触发条件从默认的 100% 降低到 10%

但是这个内存占用也太大了吧,一直占用这么多, 都没有释放的。

我先试试 GOGC=10 ./nkn-tunnel …这个

就是我用speedtest测速,通过nkntunnel,内存就会暴涨,测四五次,内存就会这么高,然后内存占用不怎么会降低

更改GC频率之后,对比之前的测试次数来说确实占用变小了,但是性能却是没之前好了。内存占用大概占用整机百分之十五左右。但是随着测试的次数增加,确实内存是在慢慢增加的,没有减少(十分钟内)

这是GC=10时,测试多次后的内存占用
入口
image
出口
image
停止测试后,内存占用一直没降下去

Go 确实是这样的,当 GC 回收了内存以后,有时候是不会返还给系统,而是留着将来用,所以表现在内存占用上,经常会观察到内存占用只涨不降。我目前的猜想是,由于 speedtest 会高速传输大量的数据,这些数据在内存里面等待包排序的过程中(因为多个 multiclient 的数据包送达顺序是很难控制好的),被申请出来以后 Go 就没有选择释放给操作系统了。

一个能减少内存占用的方案是,在 SessionConfig 里面减少 SessionWindowSize 这个参数。这个参数默认是 4<<20,内存占用应该是和这个参数成正比的。不过如果这个参数太小,有可能导致因为等数据包到达导致的发送等待,降低最后的性能(主要是 throughput)。

还有一个不常见的可能性:你有没有试过关闭 profiling 运行,然后在操作系统那边看程序的内存占用?在某些比较少见的情况下,profiling 会导致程序的内存占用高很多很多,我们之前也遇到过类似的情况。

谢谢您的解答,我曾经尝试关闭过profiling,是一样的效果。可能就是如您所说,高速传输大量的数据导致的。也可能是我开启了多个client(开启了16个),然后大量传输数据,导致的这个情况,所以现在只开启了4个或者6个,内存增长没有之前那么迅猛了 :grimacing:。还有就是您所描述的SessionConfig,降低SessionWindowSize,我会测试测试降低后的情况。