导数据时频繁出现maybe write overflow的问题,在这种状态下能持续地运行一段时间,但是过一会leader就会stepped down。下图是在公司的机器上模拟出来的,通过自己构造的多属性(30多个)数据集,能重现这个问题。
查询sofa-rpc的issue,再次找到了这个https://github.com/sofastack/sofa-rpc/issues/551。
原因
RPC在写出数据的时候,会检测当前的ChannelOutboundBuffer的大小,如果超过了WRITE_BUFFER_HIGH_WATER_MARK(默认64K),就会限流,报write overflow的异常。
这个是为了保护客户端,防止无界的ChannelOutboundBuffer被打爆,导致资源耗尽。
通常情况下,网络有问题,导致写出失败;或者下游压力太大,不能处理这么多网络包的时候会出现这样的异常。
解决办法:
建议首先排查网络环境(网卡打满也是一种)
网络环境没问题的情况下,看下是否是流量过大,导致下游处理不过来。,如果是这种,可能意味着,这就是压测的瓶颈了。可以评估下游扩容,性能优化等方式来解决。
如果确实认为64k 也不够用. 可以自行调整
-Dbolt.netty.buffer.low.watermark
-Dbolt.netty.buffer.high.watermark
值自己算一下,默认是32*1024 和64*1024
我决定先自己验证一下到底是网络的问题还是下游处理能力的问题,怎么验证呢?让follower节点的状态机应用日志的部分执行空方法,不写数据到rocksdb,这样leader和follower之间就只有rpc通信,也就是同步日志的部分了。
经测试证明,只有rpc通信的时候是服务非常稳,没有报错,说明就是下游处理不过来了。
将水位的限制调大。
https://github.com/zhoney/hugegraph/pull/45/ 在自己造的数据集上能持续导入了,虽然在导入了几个小时后还是会有busy 异常,但是目前已经持续导入了8个多小时了,相比于昨天自测时稳定了许多。
主要改动点如下:
- 优化follower的状态机代码,将解压缩反序列化部分也交给store-backend线程来做,提高follower的处理吞吐量;
- 调高bolt rpc的高水位限制,此前是2M,现在是20M,调整后没有出现过write overflow的异常;
- raft node在busy的时候所有到达的grizzly线程先睡眠一会(睡眠时间加上了随机性),再抛出异常,算是进一步的优化限流;
- loader导数据的时候将batch size调为200,也算是限流的措施;
- 将raft log保存在机械盘上,试图让写raft日志率先成为瓶颈,而不要让压力到应用状态机那儿。
raft.path=raft-log
raft.election_timeout=10000
raft.snapshot_interval=3600
raft.backend_threads=56
raft.queue_size=16384
raft.queue_publish_timeout=60
raft.apply_batch=1
raft.rpc_threads=80
raft.rpc_connect_timeout=3000
raft.stepdown_when_vote_timeout=true
raft.use_replicator_pipeline=true
raft.rpc_buf_low_water_mark=10485760
raft.rpc_buf_high_water_mark=20971520
#raft.follower.dry_run=true
参考:
网友评论