Hi,

I think that the two implementations can coexist and my suggestion in MDEV-15935 about making the error packet version a "forceful" redirection would allow that. I believe that a reasonable way of doing a very graceful redirection would be as follows:

As for the redirection information, a URL would be a more flexible way of connecting and would allow things like UNIX domain sockets and named pipes to be used as redirection targets. I definitely agree that a simple host and port approach (correctly formatted to support IPv6 of course) must be accepted as a redirection by all client libraries but some form of standardization for the redirection format string is needed or at least how client libraries should interpret unknown values.

The forceful redirection has one minor problem that the advisory redirection does not have: only one redirection target can be given in the current form. The reason for multi-host redirections would be to prevent sudden spikes of new connections from happening on the server where the redirection is being done. The advisory redirection, as mentioned in MDEV-15935, could use SQL to set a session-level value which in turn opens up limitless possibilities of using it for load balanced redirection. This is probably a very minor in the grand scheme of things and having one host to redirect to is probably OK in most cases if the advisory redirection is implemented on top of the forceful one: the former would shift most of the connections away from the server and the latter would only be the final step that prevents new ones from being created.

For things like JDBC connection pools that support multiple hosts, redirections are technically already implemented: I believe they just pick another server when they get a Too many connections error. The benefits of a forceful redirection are thus minimal for these use-cases and the advisory one would be much more effective in avoiding new work from being placed on servers that are about to shut down. However even in this case the redirection error could be interpreted as an instruction to avoid using the given server for some period of time.

Markus

On 6/29/23 22:30, Lenski, Daniel via developers wrote:
Hi Sergei,

On Thu, 2023-06-29 at 15:58 +0200, Sergei Golubchik wrote:
On Jun 28, Lenski, Daniel via developers wrote:
I would like to propose a new feature in the MariaDB client-server
protocol<https://mariadb.com/kb/en/clientserver-protocol>:
application-layer redirection of client connections.

We want the MariaDB server to be able to tell clients connecting to
it, “Sorry, this server is unavailable. Connect to an alternate server
instead.” This mechanism is inspired by HTTP 302 (“temporary
redirect”) mechanism familiar to all developers of web applications,
and is intended to have similar semantics and security properties,
since these have now been widely deployed and tested for decades.

I have submitted a minimal but viable implementation of this at:

  *   https://github.com/MariaDB/server/pull/2681, server-side implementation
  *   https://github.com/mariadb-corporation/mariadb-connector-c/pull/226, MariaDB Connector/C implementation
I'm afraid MDEV-15935 is a bit confusing. There are lots of discussions
and ideas in the comments, like, using a specially modified OK packet,
using the error message, etc.
Right! I got the sense from the Jira discussion (https://jira.mariadb.org/browse/MDEV-15935) that there's a large and varied "wish lish" of different capabilities for this feature — not all of which
are practical or compatible.

It has also been open for over 5 years without an accepted implementation.

This is why I thought it would make a lot of sense to implement redirection in a very MINIMAL and SIMPLE form — but one that would already be useful in its initial form, and with a design that's
amentable to future extensibility. (Many thanks to Otto for encouraging and guiding this implementation!)

But the final consensus was to use session
tracking feature, it allows for most flexibility and user control over
how redirect is happening. To quote here:

  We'll add a new global/session variable, say, redirect_url. The value
  should be an empty string or a connection string in the conventional
  format (in the style of a connection url of C/J or C/NodeJS or C/C or
  FederatedX).

  This variable is appended to the default value of
  session_track_system_variables variable.

  When this variable is changed, the existing
  SESSION_TRACK_SYSTEM_VARIABLES implementation will send its new value
  to the client as a part of the OK packet. It's up to the client or to
  the connector to use this value or to ignore it.
I read through this proposal as well, but I didn't realize that it had been in any way chosen as the desired implementation. I am surprised, because there seems to be 2 key problems with it…

(1) Redirection targets in "URL" format will be extremely difficult to support in consistent and secure ways across client implementations.

The Connector/C library currently has no ability to parse connection "URLs" in either the Connector/J (https://mariadb.com/kb/en/about-mariadb-connector-j) or the MySQL formats (
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-jdbc-url-format.html), which are partially but fully compatible with each other, and to my knowledge there is no formal definition of
either. As far as I know, Connector/C is the basis for most higher-level languages’ connector libraries (e.g. Connector/Python).

If the redirection target can contain all the different kinds of connection information that MariaDB Connector/J URLs support (very long list of optional parameters! 
https://mariadb.com/kb/en/about-mariadb-connector-j/#optional-url-parameters), it will be very difficult to ensure that all languages’ Connector/X libraries handle all of these parameters in a
consistent and secure way when redirecting.

For example, if a *server* sends a redirect URL containing the optional `keyStorePassword` field, should a *client* library trust or attempt to use this value? I think not. Or what if Connector/J
observes the `timezone` parameter when redirecting to a new server, but Connector/C ignores it? This would be a source of inconsistent behavior and could frustrate users of the redirection feature.

Precisely in order to avoid this level of complexity, my proposal includes a *much simpler* format for the redirection target: `host[:port]`. This should be simple enough for any and all Connector/X
client libraries to implement in a uniform fashion. At the same time, it is designed to be extensible; if there are clear use cases for it, it could be extended in the future to include more complex
formats for the redirection target, such as Connector/J-style and/or MySQL-style connection URLs.

(2) Using OK packets and session-tracking, the server would have no way to enforce redirection.

As you wrote, "It's up to the client or to the connector to use this value [of redirect_url] or to ignore it."

In this form, redirection instructions sent by the server would be merely "advisory", and the server would have no way to ensure that clients stop connecting to it.

- Clients using OLD Connector libraries will continue to be oblivious to this value, and to ignore it. As all of us have experienced, old/forgotten/abandoned/unpatched client software is often used
for DECADES beyond its originally-intended lifespan.
- Clients using NEW Connector libraries can be configured to ignore the redirection value. Quite likely many of them WILL do this, since connecting to a new server is more difficult and more error-
prone than just continuing to send queries to the already-connected server.

This "advisory" redirection would seem to be greatly limited in the kind of use cases it supports. If servers sending redirection information can't RELY ON clients disconnecting from them, then they
can't use redirection as a prelude to shutting down the server.

This is why my proposal instead includes the redirection information in an ERROR packet: supporting clients will be able to follow the redirection (or simply disconnect if they don't want to follow
redirects, e.g. `mariadb --no-follow-redirects`), while older clients will be disconnected with a comprehensible error message. In this way, a MariaDB server will be able to RELY ON clients
disconnecting from it, which will simplify and clarify the usage of redirection for server shutdown. Note that my initial proposal only involves sending ER_SERVER_REDIRECT error packets to *newly-
connecting* clients; in the future, it could also be extended to send similar packets to *already-existing* clients, for example for load-balancing purposes.



Thanks,

Daniel Lenski
Amazon RDS MySQL/MariaDB engine team
_______________________________________________
developers mailing list -- developers@lists.mariadb.org
To unsubscribe send an email to developers-leave@lists.mariadb.org
-- 
Markus Mäkelä, Senior Software Engineer
MariaDB Corporation