WL#13327: Accept connections only if destinations are available
Motivation
Currently MySQL Router binds to the incoming socket at startup and keeps it open unconditionally.
That makes Load-Balancers believe that Router is able to handle traffic and forward MySQL connections to Router which will fail as if no destinations are available.
Goal
- Only bind to the sockets if destinations are available.
- Close incoming socket if no destinations are available (e.g. quorum is lost)
The destination of a route is considered invalid when Router either cannot determine a destination or cannot contact it. A routing strategy provides a set of valid destinations based on list of potential destinations and their availablity; this set is evaluated for each route separately. In case of static routing, the list of potential destinations is defined in configuration file and availability is determined by Routing Plugin as it tries to establish client connections. In case of InnoDB Cluster routing, the list of potential destinations is provided by cluster's metadata and availability is determined by MD Cache Plugin using various rules (i.e. quorum, whether a node is in ONLINE state, whether a node is hidden, etc); note that MD Refresh failure results in an empty list of potential destinations.
- FR1
- if a route has a non-empty set of valid destinations and its listening port is closed, its listening port MUST be opened.
- FR2
- if a route has an empty set of valid destinations and its listening port is open, its listening port MUST be closed.
- FR3
- if router fails to open a listening socket at startup, it MUST shutdown.
- FR4
- if router fails to open a listening socket after startup was finished, it MUST retry to open the listening socket.
- FR5
- retry on a listening socket open operation MUST be done until it succeeds, with an implementation defined retry interval.
- NR1
- a connection to a valid destination MAY fail.
- NR2
- when a valid destinations changes is implementation dependent.
Connection handling
Currently Router opens its listening sockets when it starts and they are kept open until Router shuts down. That could be misleading for external applications that may assume that they can forward traffic even though Router may not have any destinations on its part. To avoid that listening socket MUST be shut down if there are no valid destinations. New connections MUST NOT be accepted if there are no valid destinations. If any destination starts to be valid again then listening socket MUST be opened and new connections MUST be accepted. If socket cannot be reopened then a proper error message MUST be logged and the socket SHOULD be reopened on a next possible occasion.
Dynamic routing
Routing destination is not valid when when the destination node information is missing from the metadata. If a socket cannot be opened then it should be reopened on a next MetaData refresh.
Metadata unavailable
Client connections MUST be closed when the group is overloaded and when the
disconnect_on_metadata_unavailable
option is set to true. If the group is
overloaded and disconnect_on_metadata_unavailable
is set to false then
any of the existing connections MUST NOT be closed.
disconnect_on_metadata_unavailable
is not a new feature introduced in this
worklog.
Static routing
Depending on the routing policy listening sockets are handled in the following way:
- first-available - listening socket CANNOT be closed in this case.
- next-available - if there are no destinations that could be connected by the Router then listening socket MUST be closed. If listening socket is closed then it is not possible to reopen it.
- round-robin - if there are no destinations that could be connected by the Router then listening socket MUST be closed. If any of the destinations could be connected again then listening socket MUST be opened. If the socket cannot be reopened then it SHOULD be reopened when any of the destinations become connectible again.
Note: in case of static routing destination information is obtained on accepting new connections.
Hidden instances
Routing destination is not valid when the instance is hidden.
Router can be instructed to disconnect existing connections to instances that
are marked to be hidden by using the disconnect_existing_sessions_when_hidden
option. In case when there are no valid destinations
left and some nodes are marked as hidden then there are two cases:
disconnect_existing_sessions_when_hidden=true
- existing connections MUST be disconnected.disconnect_existing_sessions_when_hidden=false
- existing connections MUST NOT be disconnected.
disconnect_existing_sessions_when_hidden
is not a new feature introduced
in this worklog.
Routing policies
If there are no valid destinations for the read-only routing then:
- if the routing policy allows to do the fallback to the primary node and there are existing destinations for the primary then listening read-only socket MUST NOT be closed.
- if the routing policy allows to do the fallback to the primary node but there are no existing destinations for the primary then listening read-only socket MUST be closed.
- if the routing policy do not allow to do the fallback to the primary node then listening read-only socket MUST be closed.
If there are no valid destinations for the read-write routing then the corresponding Router listening read-write socket MUST be closed.
Valid destinations update summary based on destination-class
Policy | Valid destinations update: | Retry: |
---|---|---|
metadata-cache | metadata cache update | metadata refresh (ttl) |
round-robin | failed connect | 3s timeout |
first-available | never | N/A |
next-available | failed connect | never |