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

Permanent id: UUID or node name? #715

Open
joaofl opened this issue Sep 11, 2022 · 8 comments
Open

Permanent id: UUID or node name? #715

joaofl opened this issue Sep 11, 2022 · 8 comments

Comments

@joaofl
Copy link

joaofl commented Sep 11, 2022

I recently started experimenting with zyre, and so far It has been a great experience (congrats for the dev team!).

But there is one specific requirement in my use case which I still could not tell how to address. I will have one node on the network with some logical "leadership", named MASTER. It will delegate functions to the other nodes on the network, which will in turn execute tasks, and eventually communicate back to the master what was done.

To my understanding, for that to happen I would need to keep track of the node name and UUID upon the reception of a message, in some sort of dictionary, such that I can tell later which UUID the node with name "MASTER" has, so I can WHISPER to it. But many problem rise the minute I try to keep track of the pair UUID:name. That is because the UUID is random, so each time a node restarts, my dictionary may not be yet up to date, and lead to undesirable behaviors.

So I see two solutions here... One is to have a fixed UUID to the entire lifetime of the product. In that case the UUID could be a hash of the MAC for example. But yet, I saw no way to set the UUID manually at the node creation. That would enable predictable constant and yet unique UUIDS.

Another approach could be to have some sort of get_peer_uuid_from_name method. So that way I could WHISPER to the MASTER without necessarily keeping track of its UUID.

There is already a method in "zyre_peer.h" that almost accomplish that: zyre_peer_name, but it is not exposed to the outside. That is used by the zyre_print(node) method, which already matches the UUID and the name of each known peer.

Meaning that the information is already there, but I cannot find the means to use it in my favor.

I: 22-09-11 21:20:55 zyre_node: dump state
I: 22-09-11 21:20:55  - name=node00 uuid=F43D738091434BDB893814089E51D0FB
I: 22-09-11 21:20:55  - endpoint=tcp://10.0.0.20:49161
I: 22-09-11 21:20:55  - discovery=beacon port=5670 interval=0
I: 22-09-11 21:20:55  - headers=0:
I: 22-09-11 21:20:55  - peers=2:
I: 22-09-11 21:20:55    - uuid=B2A896FB3F594B63B6B468A67125FD66 name=MASTER endpoint=tcp://10.0.0.20:49158 connected=yes ready=yes sent_seq=1 want_seq=2
I: 22-09-11 21:20:55    - uuid=5036DF662EAF423FB536C9C3270AEE81 name=node02 endpoint=tcp://10.0.0.20:49159 connected=yes ready=yes sent_seq=1 want_seq=1
I: 22-09-11 21:20:55  - own groups=1:
I: 22-09-11 21:20:55    - GROUP
I: 22-09-11 21:20:55  - peer groups=1:
I: 22-09-11 21:20:55    - GROUP
I: 22-09-11 21:20:55      - B2A896FB3F594B63B6B468A67125FD66
I: 22-09-11 21:20:55      - 5036DF662EAF423FB536C9C3270AEE81

Any suggestions on how to correctly address that?

I am willing to contribute to project, and add any functionalities if they make sense at all.

Kind regards,

@sthoduka
Copy link
Contributor

To my understanding, for that to happen I would need to keep track of the node name and UUID upon the reception of a message, in some sort of dictionary, such that I can tell later which UUID the node with name "MASTER" has, so I can WHISPER to it. But many problem rise the minute I try to keep track of the pair UUID:name. That is because the UUID is random, so each time a node restarts, my dictionary may not be yet up to date, and lead to undesirable behaviors.

This was how we ended up doing it for a project. As soon as a node is restarted, it should send an 'ENTER' event, which contains both the new UUID and node name, so you would update any out-of-date entries in your dictionary. You could also remove old entries from the dictionary on every 'EXIT' event. We didn't have any issues with out-of-date mappings, but we also didn't run it for very long periods, so I can't say for sure.

Another solution that was suggested previously (#526) was to set a header for the node (for example with its node name). You could then query the header of each peer to find the master.

Another related issue: #649 (this also references a PR in which zyre_get_peer_name was exposed in the API, and then removed)

@joaofl
Copy link
Author

joaofl commented Sep 12, 2022

@sthoduka Thanks for your answer.

But I still have some questions:
If the network is all up, except this last node, who needs to talk to master. So it joins the network at last. Would it get "ENTER"s from the nodes already in the network? If not, how would one keep track?
I have many concerns on keeping this table on my own, since I don't have full understanding of the protocol. In this comment another user shared a bad experience with that, and ended up going for the header's solution.

But given that the name is already present in the message, I believe its inefficient to add another name-like string to fit that purpose. The current peer's name does not allow much to be done with it the current way.

Do you know the reason why the zyre_get_peer_name method was later removed?

@joaofl
Copy link
Author

joaofl commented Sep 12, 2022

Another question in the same direction: Would it be possible/feasible/practical to set a UUID during node's creation to achieve a fixed UUID?

@sthoduka
Copy link
Contributor

If the network is all up, except this last node, who needs to talk to master. So it joins the network at last. Would it get "ENTER"s from the nodes already in the network? If not, how would one keep track?

yes, a new node entering the network receives 'ENTER' events from all other nodes that are already on the network. You can test this by running multiple instances of zpinger.

Do you know the reason why the zyre_get_peer_name method was later removed?

I don't know exactly why. You can see the commit message here: 777c78a#diff-e857acc9d05541b3024a5b4f009fa3b9

Another question in the same direction: Would it be possible/feasible/practical to set a UUID during node's creation to achieve a fixed UUID?

Also something I'm not sure about. I guess this was also the original question in #526

@joaofl
Copy link
Author

joaofl commented Sep 14, 2022

Thanks @sthoduka , that answer some questions. And indeed, in my first experiments, a simple dictionary being updated at ENTERs and EXISTs can already give a lot.

I have another (unrelated) question if I may: How do you suggest and see as the best approach to implement the REQ/REP pattern alongside with zyre? Should one implement that manually, with some shared input queue, timeout, etc, or can zmq sockets be used in parallel just fine? Does zyre intend or plan to have this functionality at any time? If not, do you know why?

@sthoduka
Copy link
Contributor

hi, sorry for the late response. I'm not the best person to answer that since I'm not really involved in the development of zyre.

Should one implement that manually, with some shared input queue, timeout, etc, or can zmq sockets be used in parallel just fine?

I think you should be able to use zmq sockets in parallel without a problem

@sunipkm
Copy link

sunipkm commented Sep 26, 2022

I think my wrapper for zyre kinda takes care of this problem, see if it suites your use case. https://github.com/sunipkm/peernet.git

I have also built a python wrapper for it, in case you find it useful.

@joaofl
Copy link
Author

joaofl commented Oct 5, 2022

@sunipkm, thanks for the link. Unfortunately I had already implemented something around that, and could not learn from your experience on time. But congrats for the good looking code.

What solved my problem was to keep track of names X uuids on a map. Something like below:

int Node::ProcessEvent(zyre_event_t * current_event) {

    if (streq (zyre_event_type(current_event), "ENTER")) {
//        Add nodes id and name to the known-nodes list
//        cout << "Node " << zyre_event_peer_name(current_event) << " entered the network" << endl;
//        TODO: check if node name is already in the network to ensure there are no duplicates and undefined behavior
        peerUUIDs[zyre_event_peer_name(current_event)] = zyre_event_peer_uuid(current_event);
    }
    else if (streq (zyre_event_type(current_event), "EXIT")) {
//        Remove nodes id and name to the known-nodes list
//        cout << "Node " << zyre_event_peer_name(current_event) << " left the network" << endl;
        auto it = peerUUIDs.find(zyre_event_peer_name(current_event));
        peerUUIDs.erase(it);
    }
...

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