lni / dragonboat

A feature complete and high performance multi-group Raft library in Go.
Apache License 2.0
4.99k stars 534 forks source link

Use gossip sync raftAddress maybe has a question. #234

Closed xkeyideal closed 2 years ago

xkeyideal commented 2 years ago

Note: for reported bugs, please fill in the following details. bug reports without detailed steps on how to reproduce will be automatically closed.

Dragonboat version

v3.3.5

The hashicorp/memberlist Delegate interfaces, NodeMeta method for the metadata store. Dragonboat framework use the NodeMeta sync raftAddress, but my gossip example codes also use NodeMeta sync some datas, I see the memberlist ans serf source codes for use NodeMeta method sync data, need call memberlist.UpdateNode method, the method will trigger NodeMeta. I can't found the memberlist.UpdateNode in dragonboat framework.

func (d *eventDelegate) start() {
    d.stopper.RunWorker(func() {
        for {
            select {
            case <-d.stopper.ShouldStop():
                return
            case e := <-d.ch:
                if e.Event == memberlist.NodeJoin || e.Event == memberlist.NodeUpdate {
                    d.nodes.Store(e.Node.Name, string(e.Node.Meta))
                } else if e.Event == memberlist.NodeLeave {
                    d.nodes.Delete(e.Node.Name)
                } else {
                    panic("unknown event type")
                }
            }
        }
    })
}

type delegate struct {
    raftAddress string
}

func (d *delegate) NodeMeta(limit int) []byte {
    return []byte(d.raftAddress)
}
func (d *delegate) NotifyMsg([]byte)                           {}
func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte { return nil }
func (d *delegate) LocalState(join bool) []byte                { return nil }
func (d *delegate) MergeRemoteState(buf []byte, join bool)     {}
// Resolve returns the current RaftAddress and connection key of the specified
// node. It returns ErrUnknownTarget when the RaftAddress is unknown.
func (n *NodeHostIDRegistry) Resolve(clusterID uint64,
    nodeID uint64) (string, string, error) {
    target, key, err := n.nodes.Resolve(clusterID, nodeID)
    if err != nil {
        return "", "", err
    }
    addr, ok := n.gossip.GetRaftAddress(target)
    if ok {
        return addr, key, nil
    }
    return "", "", ErrUnknownTarget
}

GetRaftAddress will not found target.

So I think the eventDelegate will not get the e.Node.Meta, if you don't call memberlist.UpdateNode, the e.Node.Meta will be empty byte array.

I'm using dragonboat multi raft framework develop my project, and use gossip configure. And I use memberlist gossip framework sync some business data. When I use memberlist delegate meta, I see your dragonboat codes, and my code is same to you. I found the problem, then I call memberlist.UpdateNode first solve it. All cluster machine can received the meta data.

lni commented 2 years ago

Sorry but it is not very easy to actually understand what you really want to express.

xkeyideal commented 2 years ago

Yes, it is very easy, and I use it in my application too. I use gossip meta sync datas. I call memberlist.UpdateNode, otherwise the metadata of this node will not be synchronized to other nodes.

You had see the issue, the dragonboat should be OK about sync gossip metadata. Thanks for your answer.