sofastack / sofa-jraft

A production-grade java implementation of RAFT consensus algorithm.
https://www.sofastack.tech/projects/sofa-jraft/
Apache License 2.0
3.59k stars 1.15k forks source link

jraft-spring-boot-starter || NodeManager设计目的的作用? #939

Closed googlefan closed 1 year ago

googlefan commented 1 year ago

我们提供了基于spring boot 版本了么?

googlefan commented 1 year ago

追加一个问题描述,希望 大佬看到 能 帮忙回复一下: version: 1.3.12 问题: 无法获取leader 节点进行任务提交 我将jraft-core 封装到 jraft-spring-boot-starter ,做了自动装配Node、RaftGroupService的实例, 按我所理解, 当集群启动后,NodeManage.nodeMap 应该能收集到所有的集群的peers,但是我的项目启动后,主从启动稳定了,各自的NodeManage.nodeMap 只有自身的 Node节点信息,排查了很多地方,不知道为什么,代码我跟踪到 : AppendEntriesRequestProcessor.select() 方法了, 发现 在这块有针对 NodeManager 的管理 代码如下:

final AppendEntriesRequestHeader header = (AppendEntriesRequestHeader) reqHeader;
            final String groupId = header.getGroupId();
            final String peerId = header.getPeerId();
            final String serverId = header.getServerId();
            final PeerId peer = new PeerId();
            if (!peer.parse(peerId)) {
                return executor();
            }
            final Node node = NodeManager.getInstance().get(groupId, peer);

debug发现 NodeManager.getInstance() 只能加入自己的peer节点, 这就导致我在提交Task任务的时候 想通过 NodeManager.getInstance().get(node.getGroupId(), node.getLeaderId()); 去获取leader 节点 总是为Null. 不知道是我使用方式的问题,还是这块源代码处理的问题,大佬是时间帮忙 解惑一下.

fengjiachun commented 1 year ago

你好,如果我没理解错你的问题的话,估计是你对 jraft-core 这一层有一定的误解,

jraft-core 这一层,本质上它只是个编程接口,也就是说 Node 只能告诉你它当前是 Leader 角色还是 Follower 角色(或者是 Leaner),如果你要 apply task,也就是发起一个请求,那么有效步骤是:

  1. 获取 leader 节点(并不一定是本机,也可能是远程的节点)
  2. 如果 leader 在本机节点,直接 apply,如果在远程节点,调用 RPC apply

上面两个步骤, jraft-core 这一层是没有做的,也就是说你除了要实现自己的状态机,还需要实现上面两个步骤 如果要自行实现上面两个步骤,就在当前的项目里 RheaKV 模块是一个和好的参考例子,下面我简单给出一些重要的点:

  1. RouteTable.java 是 client 端的路由表工具类,可参考 rheakv 如何使用的
  2. leader 节点有可能变更的,如果一个请求到了对应节点,而该节点已经 stepdown,并且其他节点已经成为 leader ,要怎么做:
    • 一种办法是返回 Not_Leader 错误给客户端,客户端重新刷新路由表再讲请求发送到新的 leader 节点(RheaKV 用的这个方法,参考 RheaKV 的重试逻辑)
    • 另一种就是在 server 端直接转发(目前我这里没有这么做的案例,可能存在的一些 corner case 要提前考虑清楚)

以上,如果还有细节问题,可在这个 issue 里展开讨论

googlefan commented 1 year ago

issue 949 issue 949 也是我针对Jraft 提出的疑问以及提出的优化需求,可能不太成熟,您参考一下. 您提到的 解决方案 我有在 example 中有看到 ,我目前的处理方式也应该是按您给的步骤来的, 只是看到 jraft-core 有提供NodeManage.nodeMap 这个针对Node节点进行管理的实例,我以为 可以通过 NodeManage.nodeMap 来获取所有集群节点的RPC服务,(这个 管理是否需要我们集成者来进行维护,才可以使用呢?如果是的话, 那么维护的步骤 大致是怎样的? 能否更新到 操作手册文档中呢 ) 是这样的么? 这个类的设计的目的?

fengjiachun commented 1 year ago

只是看到 jraft-core 有提供NodeManage.nodeMap 这个针对Node节点进行管理的实例,我以为 可以通过 NodeManage.nodeMap 来获取所有集群节点的RPC服务,(这个 管理是否需要我们集成者来进行维护,才可以使用呢?如果是的话, 那么维护的步骤 大致是怎样的? 能否更新到 操作手册文档中呢 ) 是这样的么? 这个类的设计的目的?

NodeManager 是 jraft 内部为了实现单个进程内多个 raft group 共享同一个网络端口设计的,不是给集成着或者用户使用的

googlefan commented 1 year ago

只是看到 jraft-core 有提供NodeManage.nodeMap 这个针对Node节点进行管理的实例,我以为 可以通过 NodeManage.nodeMap 来获取所有集群节点的RPC服务,(这个 管理是否需要我们集成者来进行维护,才可以使用呢?如果是的话, 那么维护的步骤 大致是怎样的? 能否更新到 操作手册文档中呢 ) 是这样的么? 这个类的设计的目的?

NodeManager 是 jraft 内部为了实现单个进程内多个 raft group 共享同一个网络端口设计的,不是给集成着或者用户使用的

明白了, 确实被误导了 ,这块 , 那咱们未来有计划 支持 集群Nodes的管理方案么? 这样作为使用者 更容易来做集成了 我想