WL#13787: Support hiding instances from applications

Affects: Server-8.0   —   Status: Complete

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

  1. 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.

  2. 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._hidden with value true should be considered hidden. Instances that do not have attribute tag._hidden or have this attribute with any other value than true should 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_hidden with value = false should be considered as "dont_disconnect_existing". Instances that do not have that attribute or have it with any other value than false should 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
    • false the node should be used as a destination for new client connections
    • true the node should NOT be used as a destination for new client connections
  • default value: false
    • should be applied when the hidden is not present in tags or it has a value other than boolean
_disconnect_existing_sessions_when_hidden
  • specifies if in case of the hidden: true the existing client connections to the should be closed
  • boolean JSON type
    • true the existing client connections to the node should all be closed if _hidden: true
    • false the 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_hidden is not present in tags or it has a value other than one of tan boolean

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.