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

不同 Raft 集群非预期通信导致 Raft 状态异常 #1012

Closed
luckyxiaoqiang opened this issue Jul 17, 2023 · 3 comments · Fixed by #1033
Closed

不同 Raft 集群非预期通信导致 Raft 状态异常 #1012

luckyxiaoqiang opened this issue Jul 17, 2023 · 3 comments · Fixed by #1033

Comments

@luckyxiaoqiang
Copy link

Describe the bug

我们的应用使用 JRaft 作为持久化模块,部署在 K8S 中(Statefulset)。Raft 集群节点之间通过 K8S headless 域名通信。应用存在多租户场景,同一个 K8S 集群中会部署多个应用集群。

当应用的多个集群同时滚动更新时,Pod IP 会变动,可能原先 A 集群中节点 IP,滚动更新后被分配到了 B 集群中的节点。
滚动更新前:

Pod IP
app-cluster-a-0 10.10.10.10
app-cluster-a-1 10.10.10.11
app-cluster-a-2 10.10.10.12
app-cluster-b-0 10.10.20.10
app-cluster-b-1 10.10.20.11
app-cluster-b-2 10.10.20.12

滚动更新后:

Pod IP
app-cluster-a-0 10.10.10.13
app-cluster-a-1 10.10.10.11
app-cluster-a-2 10.10.10.12
app-cluster-b-0 10.10.10.10
app-cluster-b-1 10.10.20.11
app-cluster-b-2 10.10.20.12

更新前 app-cluster-a-0 的 IP 10.10.10.10 在更新后被分配给了 app-cluster-b-0。

由于域名解析存在延迟,包括 JVM、GRPC、K8S CoreDNS 等各个层面,更新后集群 a 中的节点(app-cluster-a-1 或 app-cluster-a-2)通过域名连接 app-cluster-a-0 时,实际可能连接到 app-cluster-b-0 节点。会带来的 2 大问题:

  • app-cluster-a-0 一直收不到集群 a 中 leader 的追加日志、心跳等请求,实际上 leader 的请求发送到了 app-cluster-b-0(新 IP 为 10.10.10.10),会有"Peer id not found" 错误。app-cluster-a-0 一直尝试 preVote,但一直失败,因为 app-cluster-a-1 或 app-cluster-a-2 已经选出了 leader。这个状态一直持续,无法收敛。
  • RouteTable refresh 的时候,如果是通过 app-cluster-a-0 来获取 leader 信息,则请求可能被发送到 app-cluster-b-0(10.10.10.10),获取的 leader 实际上是 b 集群的 leader,后面获取 Configuration 也会获取到 b 集群的,会导致上层的请求路由窜集群。原因是 RouteTable.refreshLeader 中的 getLeader 请求没有设置 Peer id,其他集群的节点也会正常响应。

问题与 Issue #683 有些类似,但 PR #690 并不能彻底解决我们面临的问题。

Expected behavior

期望 JRaft 能够解决 DNS 解析延迟带来的问题:

  • JRaft 能够严格校验 Raft 请求的 Cluster/Peer 等信息,避免跨 Raft 集群通信的可能
  • JRaft 能够及时检测到 DNS 解析延迟避免一些非预期行为,及时使用 DNS 最新解析恢复集群状态

Actual behavior

不同 Raft 集群非预期通信导致 Raft 状态异常

Steps to reproduce

Minimal yet complete reproducer code (or GitHub URL to code)

Environment

  • SOFAJRaft version: 1.3.9
  • JVM version (e.g. java -version):
  • OS version (e.g. uname -a):
  • Maven version:
  • IDE version:
@killme2008
Copy link
Contributor

  1. jraft 当然有严格校验 cluster 和peer
  2. DNS 延迟不是一个类库能完全解决的,操作系统, jvm 都可能去缓存这个信息,我觉的你们更应该想的是怎么去避免这种 ip 的短期复用。

@luckyxiaoqiang
Copy link
Author

  1. jraft 当然有严格校验 cluster 和peer
  2. DNS 延迟不是一个类库能完全解决的,操作系统, jvm 都可能去缓存这个信息,我觉的你们更应该想的是怎么去避免这种 ip 的短期复用。
  1. 部分场景没有严格校验,比如 RouteTable.refreshLeader。
  2. 应用层或部署环境,是可以去做一些工作来尽量避免 IP 短期复用问题的,但也期望类库能够在连接到错误集群时能够及时收敛。

@killme2008
Copy link
Contributor

  1. Good catch! 可以提个修复
  2. 应用层或部署环境,是可以去做一些工作来尽量避免 IP 短期复用问题的 —— 这才是根本解决办法。

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

Successfully merging a pull request may close this issue.

2 participants