-
Notifications
You must be signed in to change notification settings - Fork 370
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
INDY-1112: change primeries election procedure for backup instances. #539
INDY-1112: change primeries election procedure for backup instances. #539
Conversation
Could one of the committers please verify this patch? |
Now primaries for backup instances are choosen in round-robin manner always starting from primary. If the next node is a primary for some instance then this node is skipped. So the first non-primary node is choosen as primary for current instance. Such approach allows to avoid election of instances of the same node as a primeries for different instances. The election procedure of the primary for master instance is not changed. Signed-off-by: Sergey Shilov <[email protected]>
a9765be
to
8773548
Compare
plenum/server/primary_selector.py
Outdated
logger.trace("{} selected {} as next primary node for instId {}, " | ||
"viewNo {} with rank {}, nodeReg {}".format( | ||
self, name, instance_id, self.viewNo, rank, nodeReg)) | ||
assert name, "{} failed to get next primary node name".format(self) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we "assert name" before logging that primary was selected?
What should we do if name is None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course "assert name" should be before logging.
If name is None then Apocalypse has come. It can not be None by design, otherwise implementation is incorrect.
plenum/server/node.py
Outdated
''' | ||
if instance_id == 0: | ||
primary_rank = self.poolManager.get_rank_by_name( | ||
replica.primaryName.split(":", 1)[0], nodeReg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't use name
variable here instead of replica.primaryName.split(":", 1)[0]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because replica.primaryName in fact is not just node name, it has a form "node_name:instance_id". So it would be nice to rename replica.primaryName to replica.primaryInstanceName, I'll check how wide re-factoring it will cause.
plenum/server/primary_selector.py
Outdated
def next_primary_replica_name_for_backup(self, instance_id, master_primary_rank, | ||
primaries, nodeReg=None): | ||
""" | ||
Returns name of the next node which is supposed to be a new Primary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please correct the description since it's not a real round robin, but it takes into account the other primaries.
Please mention that we return two values, not just name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm... On my opinion it is pure round robin, the only thing is that we may skip some nodes, but it is round robin anyway.
As for primary for master replica - this is not round robin, I think. There is a formula that is not changed in scope of these changes:
(view_no + instance_id) % total_nodes
I really don't see round robin here.
As for returned two values - done.
plenum/server/primary_selector.py
Outdated
|
||
return name | ||
|
||
def next_primary_replica_name_for_master(self, nodeReg=None): | ||
""" | ||
Returns name of the next node which is supposed to be a new Primary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please mention that we return two values, not just name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
plenum/server/primary_selector.py
Outdated
|
||
return name | ||
|
||
def next_primary_replica_name_for_master(self, nodeReg=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a unit test for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
plenum/server/primary_selector.py
Outdated
name = self.next_primary_node_name_for_master(nodeReg) | ||
return name, Replica.generateName(nodeName=name, instId=0) | ||
|
||
def next_primary_replica_name_for_backup(self, instance_id, master_primary_rank, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a unit test for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -2354,15 +2354,42 @@ def lost_master_primary(self): | |||
self._schedule_view_change() | |||
|
|||
def select_primaries(self, nodeReg: Dict[str, HA]=None): | |||
primaries = set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add an integration test for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Build a set of names of primaries, it is needed to avoid | ||
duplicates of primary nodes for different replicas. | ||
''' | ||
for instance_id, replica in enumerate(self.replicas): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to keep track of 'old' primaries just to avoid selecting the same primaries as was before?
Please add a test for this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -2354,15 +2354,42 @@ def lost_master_primary(self): | |||
self._schedule_view_change() | |||
|
|||
def select_primaries(self, nodeReg: Dict[str, HA]=None): | |||
primaries = set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move all this logic to primary_selector
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have not information about primaries on primary_selector level.
plenum/server/primary_selector.py
Outdated
|
||
return name | ||
|
||
def next_primary_node_name_for_backup(self, instance_id, nodeReg=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this method at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it is already deleted.
plenum/server/primary_selector.py
Outdated
@@ -54,14 +54,56 @@ def next_primary_node_name(self, instance_id, nodeReg=None): | |||
|
|||
return name | |||
|
|||
def next_primary_replica_name(self, instance_id, nodeReg=None): | |||
def next_primary_node_name_for_master(self, nodeReg=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this method must be private (with _ prefix).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Signed-off-by: Sergey Shilov <[email protected]>
Test this please. |
Signed-off-by: Sergey Shilov <[email protected]>
Signed-off-by: Sergey Shilov <[email protected]>
assert primariesIdxs[1] == 1 | ||
|
||
master_node = txnPoolMasterNodes[0] | ||
client, wallet = stewardAndWalletForMasterNode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use SDK here?
yield nodes | ||
|
||
|
||
def test_primaties_selection(txnPoolNodeSetWithElector): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a typo in the test name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
yield nodes | ||
|
||
|
||
def test_primaties_selection(txnPoolNodeSetWithElector): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please split the test into a multiple of small tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
primaries = set() | ||
view_no_bak = node.elector.viewNo | ||
node.elector.viewNo = view_no | ||
for instance_id in range(0, node.replicas.num_replicas): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we write it in a more simple way without a loop and if-else conditions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Re-factored.
Signed-off-by: Sergey Shilov <[email protected]>
…oolManager. Now a node adds itself to nodeReg during catch-up of pool ledger. Signed-off-by: Sergey Shilov <[email protected]>
Signed-off-by: Sergey Shilov <[email protected]>
test this please |
Signed-off-by: Sergey Shilov <[email protected]>
plenum/server/pool_manager.py
Outdated
@@ -272,6 +272,18 @@ def nodeHaChanged(self, txn): | |||
# TODO: Check if new HA is same as old HA and only update if | |||
# new HA is different. | |||
if nodeName == self.name: | |||
# Update itself in node registry if needed | |||
(ip, port) = self.node.nodeReg[nodeName] | |||
if ip != txn[DATA][NODE_IP] or port != txn[DATA][NODE_PORT]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if txn conatins IP only (or PORT only)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bad things will happen in this case... Additional checks should be added.
Signed-off-by: Sergey Shilov <[email protected]>
Test this please. |
…yperledger#539) * INDY-1112: change primeries election procedure for backup instances. Now primaries for backup instances are choosen in round-robin manner always starting from primary. If the next node is a primary for some instance then this node is skipped. So the first non-primary node is choosen as primary for current instance. Such approach allows to avoid election of instances of the same node as a primeries for different instances. The election procedure of the primary for master instance is not changed. Signed-off-by: Sergey Shilov <[email protected]> * Add some stylistical fixes, add comments. Signed-off-by: Sergey Shilov <[email protected]> * Add test for primary demotion and promotion. Signed-off-by: Sergey Shilov <[email protected]> * Add test for primaries selection routines. Signed-off-by: Sergey Shilov <[email protected]> * Re-factor primary selector tests. Signed-off-by: Sergey Shilov <[email protected]> * Remove adding of node itself to nodeReg during initialisation of txnPoolManager. Now a node adds itself to nodeReg during catch-up of pool ledger. Signed-off-by: Sergey Shilov <[email protected]> * Fix test. Signed-off-by: Sergey Shilov <[email protected]> * Update node's HA in node registry on pool ledger catch-up reply. Signed-off-by: Sergey Shilov <[email protected]> * Add separate checks for IP/port to be updated for HA and cliHA. Signed-off-by: Sergey Shilov <[email protected]>
…yperledger#539) * INDY-1112: change primeries election procedure for backup instances. Now primaries for backup instances are choosen in round-robin manner always starting from primary. If the next node is a primary for some instance then this node is skipped. So the first non-primary node is choosen as primary for current instance. Such approach allows to avoid election of instances of the same node as a primeries for different instances. The election procedure of the primary for master instance is not changed. Signed-off-by: Sergey Shilov <[email protected]> * Add some stylistical fixes, add comments. Signed-off-by: Sergey Shilov <[email protected]> * Add test for primary demotion and promotion. Signed-off-by: Sergey Shilov <[email protected]> * Add test for primaries selection routines. Signed-off-by: Sergey Shilov <[email protected]> * Re-factor primary selector tests. Signed-off-by: Sergey Shilov <[email protected]> * Remove adding of node itself to nodeReg during initialisation of txnPoolManager. Now a node adds itself to nodeReg during catch-up of pool ledger. Signed-off-by: Sergey Shilov <[email protected]> * Fix test. Signed-off-by: Sergey Shilov <[email protected]> * Update node's HA in node registry on pool ledger catch-up reply. Signed-off-by: Sergey Shilov <[email protected]> * Add separate checks for IP/port to be updated for HA and cliHA. Signed-off-by: Sergey Shilov <[email protected]>
Now primaries for backup instances are choosen in round-robin
manner always starting from primary. If the next node is a primary
for some instance then this node is skipped. So the first non-primary
node is choosen as primary for current instance. Such approach allows
to avoid election of instances of the same node as a primeries for
different instances.
The election procedure of the primary for master instance is not changed.
Signed-off-by: Sergey Shilov [email protected]