Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如果follower的业务状态机队列满了,leader向follower发heartbeat请求会超时失败 #830

Closed
jackjoesh opened this issue May 12, 2022 · 7 comments

Comments

@jackjoesh
Copy link

Describe the bug

如果follower业务状态机队列满了,leader向follower发heartbeat请求会超时失败,从而follower触发onstopfollowing
基于v1.3.9.10.bugfix_2版本
NodeImpl第1963行开始的this.ballotBox.setLastCommittedIndex(Math.min(request.getCommittedIndex(), prevLogIndex));有这个问题:
if (entriesCount == 0) {
// heartbeat or probe request
final AppendEntriesResponse.Builder respBuilder = AppendEntriesResponse.newBuilder() //
.setSuccess(true) //
.setTerm(this.currTerm) //
.setLastLogIndex(this.logManager.getLastLogIndex());
doUnlock = false;
this.writeLock.unlock();
// see the comments at FollowerStableClosure#run()
this.ballotBox.setLastCommittedIndex(Math.min(request.getCommittedIndex(), prevLogIndex));
return respBuilder.build();
}

我看到过之前有两个issue讨论过这个问题:
#757
#754

但是只是对raft log的队列引入了no blocking模式,可以让外部自己判断。但是业务状态机队列满导致heartbeat请求失败,这种情况是不是也还是有问题呢?

@killme2008
Copy link
Contributor

实际遇到问题了? 业务状态机满,理论上并不影响心跳。

@jackjoesh
Copy link
Author

实际遇到问题了? 业务状态机满,理论上并不影响心跳。

是的,我理解follower在接受heartbeat请求的处理链路如下:
NodeImpl的1972行
this.ballotBox.setLastCommittedIndex(Math.min(request.getCommittedIndex(), prevLogIndex));
BallotBox第241行
this.waiter.onCommitted(lastCommittedIndex);
FSMCallerImpl第239行
public boolean onCommitted(final long committedIndex) {
return enqueueTask((task, sequence) -> {
task.type = TaskType.COMMITTED;
task.committedIndex = committedIndex;
});
}

最后的这个业务状态机队列ApplyTask是阻塞式的队列,那会造成follower处理heartbeat请求超时, 从而leader端heartbeat超时

@jackjoesh
Copy link
Author

实际遇到问题了? 业务状态机满,理论上并不影响心跳。

我们follow在启动的时候,如果要追的业务状态机数据很多,把队列打满了,就会很快造成follower onStopFollowing

@killme2008
Copy link
Contributor

嗯,你说的现象是可能存在的,这块我们再思考下。心跳会捎带 commit index 来提交日志到状态机,如果状态机长期跟不上 leader 进度也会有问题。

@jackjoesh
Copy link
Author

嗯,你说的现象是可能存在的,这块我们再思考下。心跳会捎带 commit index 来提交日志到状态机,如果状态机长期跟不上 leader 进度也会有问题。

我明白你的意思,如果状态机器长期跟不上,那个follower也是有问题的。但是最好在follower刚启动的时候,给他一定的容错时间,如果我们用raft做一些比较重的业务的时候,启动时可能就会存在追比较久的情况

@killme2008
Copy link
Contributor

这个问题可以通过一些限流来缓解, RafOptions 里的:

  • maxByteCountPerRpc 控制单个 RPC 请求大小
  • maxEntriesSize 单次发送 log 数量
  • maxBodySize 单次发送 log 字节数
  • maxAppendBufferSize 刷写磁盘最大字节数

这些参数来调节。

@jackjoesh
Copy link
Author

这个问题可以通过一些限流来缓解, RafOptions 里的:

  • maxByteCountPerRpc 控制单个 RPC 请求大小
  • maxEntriesSize 单次发送 log 数量
  • maxBodySize 单次发送 log 字节数
  • maxAppendBufferSize 刷写磁盘最大字节数

这些参数来调节。

如果限流,也是在启动的时候限制下,如果一直配置这样的参数,整体集群的tps会下降吧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants