sofastack / sofa-jraft

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

CliService addPeer,返回的status提示Status[ECATCHUP<10003>: Peer 127.0.0.1:9091 failed to catch up.] #1010

Closed developerdujunjie closed 1 year ago

developerdujunjie commented 1 year ago

Your question

CliService addPeer,返回的status提示Status[ECATCHUP<10003>: Peer 127.0.0.1:9091 failed to catch up.]

Your scenes

服务启动后,向zookeeper注册服务的ip和raft port,自己单独起了个管理服务,监听zookeeper事件,获取服务注册得ip和raft port, 然后利用jraft提供得CliService addPeer添加raft节点, Status addPeer(String groupId, Configuration conf, PeerId peer)方法中,如果config是leader节点,那么新添加得peer可以成功,如果config不是leader节点,会提示failed to catch up

Your advice

由于初始化raft集群需要预先知道服务得ip,在容器环境下无法提前预知,所以想了其他办法,在服务启动后,通过向zk注册IP和port, 然后单独有个管理服务监听注册事件,获取服务注册的ip,port并通过CliService的addPeer方法来动态组件raft集群,由于各个节点向zk注册的顺序是随机的,那如何正确使用jraft提供的CLI服务,即CliService通过ZK这种服务发现,来动态组件jraft集群呢?

Environment

daodol commented 1 year ago

我遇到了同样的问题

killme2008 commented 1 year ago

初始化还有个办法,就是节点全部启动后,使用 changePeers 批量来更改,更推荐这样。

developerdujunjie commented 1 year ago

初始化还有个办法,就是节点全部启动后,使用 changePeers 批量来更改,更推荐这样。

1,节点全部启动完成的时间不好确认,2,changPeers有三个参数,那第二个参数,如果等全部节点启动完毕,进行调用,该传什么?传一个empty是confihuration?

killme2008 commented 1 year ago
  1. 不好确定也没关系,多次 changePeers 都可以,终态稳定再提供服务就可以。 新集群 changePeers 很快的。
  2. 初始集群可以用任意启动的第一个节点做 conf,后面每次都用当前的全量 conf 覆盖即可。
developerdujunjie commented 1 year ago
  1. 不好确定也没关系,多次 changePeers 都可以,终态稳定再提供服务就可以。 新集群 changePeers 很快的。
  2. 初始集群可以用任意启动的第一个节点做 conf,后面每次都用当前的全量 conf 覆盖即可。

目前节点启动时,按你说的来做,可以依次把启动的节点通过changePeers调用,添加成功,但是在实现节点下线时(通过监听ZK Node remove事件),拿到下线节点的IP和port,通过changePeers会大概率失败,返回的status errorMsg提示Fail to get leader of group counter, Unknown leader 具体的: 比如3个节点都上线后,最终节点服务管理类,维护的configurtion peer节点列表为(192.168.1.10:9091,192.168.1.10:9092,192.168.1.10:9093);如果我通过kill -9 的方式将192.168.1.10:9092节点杀掉,杀掉的节点是随机的,并没有去管杀掉的节点当前是leader,还是follower,那么节点杀掉后,zk给节点管理服务推送节点下线的通知,节点管理服务拿到下线服务的IP和PORT,线构建newConfig=new Configuration(oldConfig).其中oldConfg为Port 9091到9093的上线peer,然后 newConfig.remove(下线peer),最后调用CliService.changePeers('groupId',oldConfg,newConfig),返回的status errorMsg就会是Fail to get leader of group counter, Unknown leader(不确定是不是,端口是9092的服务被杀掉后,剩下的两个节点一直在进行leader选举,一直没选成功...,导致始终拿不到leade peer),管理服务的做法是通过while(true)的方式,一但删除节点,changePeers返回status不是ok,就会sleep几秒,然后不断重试,直到status.isOk为true,通过break跳出while循环。但是目前来看,好像并没有作用。烦请大佬指点下,在处理节点下线时,changePeers该如何使用,或者是不是不该有changePeers方法,而应该使用removePeer方法才对呢?

killme2008 commented 1 year ago

移除节点用 removePeer, changePeers 要慎用,第一次构建集群可以。

developerdujunjie commented 1 year ago

移除节点用 removePeer, changePeers 要慎用,第一次构建集群可以。

那服务确实挂掉了,这种情况,该如何处理呢?因为服务部署在容器,如果再次部署,部署后的ip肯定会跟之前不一样,且目前按照我这种服务上下线管理机制,下线的节点大概率就一直下线了。。。。

killme2008 commented 1 year ago

removePeer 和 addPeer。 不过建议用 hostname,如果能保证 hostname 不变最好,这样就不用特别处理。

developerdujunjie commented 1 year ago

removePeer 和 addPeer。 不过建议用 hostname,如果能保证 hostname 不变最好,这样就不用特别处理。

大佬,建议用hostname,且hostname不变最好,这个没太理解,可以具体结合例子讲下吗,非常感谢🙏

developerdujunjie commented 1 year ago

removePeer 和 addPeer。 不过建议用 hostname,如果能保证 hostname 不变最好,这样就不用特别处理。

目前,在使用addPeer,在节点上线时,可以添加成功,但是,在removePeer时,在节点只有两个,然后kill掉一个的情况下,status会提示找不到leader,这种情况,是不是由于我kill掉了两个节点中的leader节点导致的,因为我看removePeer方法,先会到configuration组成的peers里面去找leader,但是leader节点被我kill掉了,而剩下的最后一个follower发现leader在election timeout后,未发心跳,触发选举,由于在follower持有的configuration里面,还持有被kill leader的ip和port,在cadidate真正进行选举前,会进行prevote,结果由于leader以下线,导致prevote一直失败,最终导致死循环,即找leader,但leader被kill掉后,candidate一直无法晋升为leader。还有种情况,是不是我kill掉的是follower,那是不是removepeer可以成功。麻烦大佬帮解答下,回复比较长,但为了更好的阐述我的问题。

killme2008 commented 1 year ago

Group 只有2个节点,杀掉一个的情况下,无法形成多数派选举了,选不出来不是很正常吗