WL#13787: Support hiding instances from applications
Motivation
Router supports distributing connections across the nodes of InnoDB cluster.
In the general case, distributing the load to all nodes is good default and expected, but the user may have reasons to exclude a node from receiving load.
Use Cases
I want to exclude a given server instance from application traffic, so that I can shut it down and perform maintenance on it (rolling upgrade, configuration changes etc), without disrupting incoming application traffic.
I want to hide a server with very high replication lag from applications, until it catches up and the replication lag is reduced.
Goal
- Router should support a per-instance metadata attribute indicating that a given instance is hidden and should not be used as a destination candidate.
JSON schema for attributes field.
Router reads the JSON from the v2_instances.attributes field and parses it assuming it is valid for the following schema:
{
"title": "v2_instances.attributes JSON field schema for mysql_innodb_cluster_metadata",
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"additionalProperties": true,
"properties": {
"tags": {
"description": "Cluster node's custom tags",
"type": "object",
"additionalProperties": true,
"properties": {
"_hidden": {
"description": "Built-in tag indicating if the node should be hidden from the user",
"type": "boolean"
},
"_disconnect_existing_sessions_when_hidden": {
"description": "Built-in tag indicating if the existing connections to the node should be dropped in case the node is hidden",
"type": "boolean"
}
}
}
}
}
- R1
-
Instances that have a metadata attribute named
tag._hiddenwith valuetrueshould be considered hidden. Instances that do not have attributetag._hiddenor have this attribute with any other value thantrueshould be considered NOT hidden. - R2
- If the instance is hidden new client connections must NOT be directed to that instance (even if that was the last remaining candidate)
- R3
-
Instances that have a metadata attribute named
tag._disconnect_existing_sessions_when_hiddenwith value =falseshould be considered as "dont_disconnect_existing". Instances that do not have that attribute or have it with any other value thanfalseshould not be considered "dont_disconnect_existing". - R4
- If the instance is "hidden" all the existing client sessions to that instance should be terminated unless it is also "dont_disconnect_existing" - in that case all the existing sessions should not be terminated by the Router even if the instance is "hidden".
- R5
- Hiding the instance should only affect the user connections. The instance should still be used by the Router when fetching the metadata, calculating the quorum etc.
- R6
- Must be supported in any topology, including ReplicaSets and Clusters
Background
We introduce a new API function in the AdminAPI that lets the user set instance specific option:
cluster.setInstanceOption("192.168.23.45:3306", "tag:A", "value");
As a result the following entry gets added to the v2_instances.attribute JSON field value:
{
"tag": {
"A": "value"
}
}
The idea is to use predefined tags to let the user define the specific behavior required from the metadata user (MySQLRouter in our case).
Newly added tags
This WL introduces the handling of the following tags by MySQLRouter:
_hidden-
- specifies if the node should be used as a destination for new client connections routed by the MySQLRouter
- boolean JSON type
falsethe node should be used as a destination for new client connectionstruethe node should NOT be used as a destination for new client connections
- default value:
false- should be applied when the
hiddenis not present intagsor it has a value other than boolean
- should be applied when the
_disconnect_existing_sessions_when_hidden-
- specifies if in case of the
hidden: truethe existing client connections to the should be closed - boolean JSON type
truethe existing client connections to the node should all be closed if_hidden: truefalsethe existing client connections to the node should NOT be closed if_hidden: true
- default value:
true- should be applied when the
disconnect_existing_sessions_when_hiddenis not present intagsor it has a value other than one of tan boolean
- should be applied when the
- specifies if in case of the
Example: set a node as hidden with shell's AdminAPI
cluster.setInstanceOption("192.168.23.45:3306",
"tag:_hidden", true);
cluster.setInstanceOption("192.168.23.45:3306",
"tag:_disconnect_existing_sessions_when_hidden", false);
The v2_instances.attribute JSON should contain:
{
"tag": {
"_hidden" : true,
"_disconnect_existing_sessions_when_hidden": false
}
}
When the MySQLRouter reads the tag from the metadata it should stop using the node as a destination for all the new connections. All the existing connections to the node that MySQLRouter is already routing should not be forcefully closed.