MySQL 9.3.0
Source Code Documentation
routing_guidelines.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024, 2025, Oracle and/or its affiliates.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0,
6 * as published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms,
10 * as designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have either included with
14 * the program or referenced in the documentation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License, version 2.0, for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#ifndef ROUTER_SRC_ROUTING_GUIDELINES_INCLUDE_ROUTING_GUIDELINES_ROUTING_GUIDELINES_H_
27#define ROUTER_SRC_ROUTING_GUIDELINES_INCLUDE_ROUTING_GUIDELINES_ROUTING_GUIDELINES_H_
28
29#include <forward_list>
30#include <functional>
31#include <map>
32#include <memory>
33#include <optional>
34#include <stdexcept>
35#include <string>
36#include <unordered_map>
37#include <vector>
38
39#ifdef RAPIDJSON_NO_SIZETYPEDEFINE
40#include "my_rapidjson_size_t.h"
41#endif
42
43#include <rapidjson/document.h>
44
45#include "my_compiler.h"
48
49namespace routing_guidelines {
50
51namespace rpn {
52class Expression;
53} // namespace rpn
54
55/// Keyword meaning that the member/cluster role is undefined.
56constexpr char kUndefinedRole[] = "UNDEFINED";
57
58/** Information about this Router instance. */
60 // std::less<> is used to allow heterogeneous lookup since key type is
61 // std::string
62 using tags_t = std::map<std::string, std::string, std::less<>>;
63
64 // port numbers configured for the named port configuration
65 uint16_t port_ro{0};
66 uint16_t port_rw{0};
67 uint16_t port_rw_split{0};
68
69 std::string local_cluster; //!< name of the local cluster
70 std::string hostname; //!< hostname where router is running
71 std::string bind_address; //!< address on which router is listening
72 tags_t tags; //!< an object containing user defined tags stored in the
73 //!< cluster metadata for that Router instance
74 std::string route_name; //!< name of the plugin which handles the
75 //!< connection
76 std::string name; //!< name of the Router instance
77};
78
79/** Information about one server destination. */
81 std::string label; //!< hostname:port as in the metadata
82 std::string address; //!< address of the server
83 uint16_t port{0}; //!< MySQL port number
84 uint16_t port_x{0}; //!< X protocol port number
85 std::string uuid; //!< @@server_uuid of the server
86 uint32_t version{0}; //!< server version in format 80401 for 8.4.1
87 std::string member_role; //!< PRIMARY, SECONDARY or READ_REPLICA, as reported
88 //!< by GR, empty string if not defined
89 std::map<std::string, std::string, std::less<>>
90 tags; //!< user defined tags stored in the cluster
91 //!< metadata for that Server instance
92 std::string cluster_name; //!< name of the cluster the server belongs to
93 std::string
94 cluster_set_name; //!< name of the ClusterSet the server belongs to
95 std::string cluster_role; //!< PRIMARY or REPLICA depending on the role of
96 //!< the cluster in the ClusterSet, empty string if
97 //!< not defined
98 bool cluster_is_invalidated{false}; //!< Cluster containing this server is
99 //!< invalidated
100};
101
102/** Information about incoming session. */
104 std::string target_ip; //!< address of the Router the session is connected to
105 int target_port{0}; //!< Router port the session is connected to
106 std::string source_ip; //!< IP address the session is connecting from
107 std::string user; //!< username the session is authenticated with
108 std::map<std::string, std::string, std::less<>>
109 connect_attrs; //!< session connect attributes by name
110 std::string schema; //!< default schema specified at connect time
111 uint64_t id{0}; //!< an auto-incremented integer number assigned by the
112 //!< router to each session
113 double random_value{0}; //!< random value in a range [0-1)
114};
115
116/** Information about query details. */
118 std::string default_schema; //!< schema currently active for the session
119 bool is_read{true}; //!< statement (or transaction) is a RO statement
120 bool is_update{false}; //!< statement (or transaction) is an update
121 bool is_ddl{false}; //!< statement is a DDL operation
122 std::map<std::string, std::string, std::less<>>
123 query_tags; //!< query specific tags specified as a comment in the SQL
124 //!< statement ( e.g.: /*-> tag1=value2,tag2=value2 */ )
125 std::map<std::string, std::string, std::less<>>
126 query_hints; //!< query specific hints specified at
127 //!< the protocol level (see WL#12542)
128};
129
130// The following warning:
131// C4275: non dll-interface class 'std::runtime_error' used as base for
132// dll-interface class 'routing_guidelines::Guidelines_parse_error'
133//
134// Can be suppressed, since Visual Studio documentation states that:
135//
136// "C4275 can be ignored in Visual C++ if you are deriving from a type in the
137// C++ Standard Library"
141 : public std::runtime_error {
142 public:
143 explicit Guidelines_parse_error(const std::vector<std::string> &errors);
144
145 const std::vector<std::string> &get_errors() const;
146
147 private:
148 std::vector<std::string> errors_;
149};
151
152/** Information about hostnames that needs to be resolved. */
154 enum class IP_version { IPv4, IPv6 };
155
156 Resolve_host(std::string address_, IP_version ip_version_)
157 : address(std::move(address_)), ip_version{ip_version_} {}
158
159 auto operator<=>(const Resolve_host &) const = default;
160
161 std::string address;
163};
164
165/**
166 * Routing guidelines engine.
167 *
168 * Responsible for traffic classification based on routing guidelines document,
169 * information about the given Router instance, incoming session information and
170 * destination servers that are provided by the metadata.
171 */
173 public:
176
179
182 delete;
183
184 /** Get routing guidelines schema describing guidelines document. */
185 static std::string get_schema();
186
187 /** Map with preprocessed resolved hostnames. */
188 using ResolveCache = std::unordered_map<std::string, net::ip::address>;
189
190 /** Factory method for creating instance of Routing_guidelines_engine
191 *
192 * @param routing_guidelines_document document content.
193 *
194 * @returns instance of the Routing_guidelines_engine class.
195 *
196 * @throws Guidelines_parse_error containing all encountered errors. */
198 const std::string &routing_guidelines_document);
199
200 /**
201 * Class representing routing guidelines route section entry.
202 *
203 * Each route references destinations that are groupped by the destination
204 * class section in the routing guideline:
205 * @code
206 * "destinations": [
207 * {
208 * "name": "secondary_dests",
209 * "match": "$.server.memberRole = SECONDARY"
210 * }
211 * ]
212 * @endcode
213 *
214 * This example provides a destination class named "secondary_dests" which
215 * matches SECONDARY nodes. Given this route:
216 * @code
217 * "routes": [
218 * {
219 * "name": "r1",
220 * "enabled": true,
221 * "match": "$.router.port.ro = 6447",
222 * "connectionSharingAllowed": true,
223 * "destinations": [
224 * {
225 * "classes": ["secondary_dests"],
226 * "strategy" : "round-robin"
227 * "priority": 0
228 * }
229 * }
230 * ]
231 * @endcode
232 * Route named "r1" uses "secondary_dests" destination class. Each node
233 * classified in the "secondary_dests" will be used according to the
234 * 'round-robin' routing strategy.
235 *
236 * If one route entry uses multiple destination classes then nodes from each
237 * destination classes are used. For example:
238 * @code
239 * "destinations": [
240 * {
241 * "classes": ["secondary_dests", "other_dests"],
242 * "strategy" : "round-robin"
243 * "priority": 0
244 * }
245 * @endcode
246 * Such route will use destinations classified as "secondary_dests" as well as
247 * "other_dests".
248 *
249 * One route may define multiple backup sinks which are used when no
250 * destinations from previous groups can be reached. They are groupped by the
251 * 'priority' setting, where lower value means higher priority, '0' means
252 * highest priority.
253 *
254 * For example:
255 * @code
256 * "routes": [
257 * {
258 * "name": "r1",
259 * "enabled": true,
260 * "match": "$.router.port.ro = 6447",
261 * "connectionSharingAllowed": true,
262 * "destinations": [
263 * {
264 * "classes": ["d1", "d2"],
265 * "strategy" : "round-robin"
266 * "priority": 0
267 * },
268 * {
269 * "classes": ["d3"],
270 * "strategy" : "round-robin"
271 * "priority": 1
272 * }
273 * ]
274 * }
275 * @endcode
276 * Route "r1" defines two destination groups that could be used, one
277 * containing destinations classified by "d1" or "d2" destination classes, and
278 * the other one containing destinations classified by "d3" destination class.
279 * Destinations classified by "d3" will be used if and only if no destination
280 * from "d1" and "d2" are reachable.
281 */
282 struct Route {
284 DestinationGroup() = default;
285 DestinationGroup(std::vector<std::string> destination_classes_,
286 std::string routing_strategy_, const uint64_t priority_)
287 : destination_classes(std::move(destination_classes_)),
288 routing_strategy(std::move(routing_strategy_)),
289 priority(priority_) {}
290
291 auto operator<=>(const DestinationGroup &) const = default;
292
293 /** References to destinations classified at specific classes. */
294 std::vector<std::string> destination_classes;
295 /** Routing strategy used to select specific destinations within this
296 * group. */
297 std::string routing_strategy;
298 /** Priority of the group. */
299 uint64_t priority{0};
300 };
301
302 Route(std::string name, std::unique_ptr<rpn::Expression> match,
303 std::vector<DestinationGroup> destination_groups,
304 const std::optional<bool> connection_sharing_allowed = std::nullopt,
305 const bool enabled = true);
306
307 auto operator<=>(const Route &) const = default;
308
309 /** Name of the route. */
310 std::string name;
311 /** Matching criterion for the given route. */
312 std::unique_ptr<rpn::Expression> match;
313 /** Destination groups used by the route. */
314 std::vector<DestinationGroup> destination_groups;
315 /** Connection sharing enabled flag. */
316 std::optional<bool> connection_sharing_allowed;
317 /** Route enabled flag. */
318 bool enabled{true};
319 };
320
321 /**
322 * Type for names of Routes changed during routing guidelines document update.
323 */
325 std::string guideline_name;
326 std::vector<std::string> affected_routes;
327 };
328
329 /**
330 * Result of route classification.
331 */
333 std::string route_name;
334 std::vector<Route::DestinationGroup> destination_groups;
335 std::optional<bool> connection_sharing_allowed;
336 std::forward_list<std::string> errors;
337 };
338
339 /**
340 * Result of destination classification.
341 */
343 std::vector<std::string> class_names;
344 std::forward_list<std::string> errors;
345 };
346
347 /**
348 * Update routing guidelines and return affected classes and routes.
349 * @param[in] new_rp - new Routing Guidelines engine
350 * @param[in] is_provided_by_user - true if guideline is provided by user
351 * or false if it is auto-generated.
352 */
353 RouteChanges update_routing_guidelines(Routing_guidelines_engine &&new_rp,
354 bool is_provided_by_user = true);
355
356 /** Get routing routing guidelines document name. */
357 const std::string &name() const;
358
359 /** Compute a route of a session. */
361 const Router_info &router_info,
362 const Sql_info *sql = nullptr) const;
363
364 /** Compute destination classes to which a MySQL instance belongs.
365 *
366 * If no suitable class is found class_names vector in returned
367 * Destination_classification will be empty. */
369 const Router_info &router_info) const;
370
371 /** Get destination names defined by routing guidelines document. */
372 const std::vector<std::string> &destination_classes() const;
373
374 /** Get list of routes defined in routing guidelines. */
375 const std::vector<Route> &get_routes() const;
376
377 /** List of hostnames that are used in routing guideline document that need to
378 * be resolved. */
379 std::vector<Resolve_host> hostnames_to_resolve() const;
380
381 /**
382 * Set the resolved hostnames cache, used when hostnames used by the routing
383 * guidelines are resolved.
384 *
385 * Can be called from a different thread, than the one performing
386 * classification.
387 */
388 void update_resolve_cache(ResolveCache cache);
389
390 /**
391 * Validate route entry string.
392 *
393 * @throw std::runtime_error when route entry is invalid
394 */
395 static void validate_one_route(const std::string &route);
396
397 /**
398 * Validate destination entry string.
399 *
400 * @throw std::runtime_error when destination entry is invalid
401 */
402 static void validate_one_destination(const std::string &destination);
403
404 /**
405 * Validate whole guidelines document.
406 *
407 * @throw std::runtime_error when guidelines doc is invalid
408 */
409 static void validate_guideline_document(const std::string &doc);
410
411 /** Get routing guidelines document that is used by the guidelines engine. */
412 const rapidjson::Document &get_routing_guidelines_document() const;
413
414 /** Check if routing guideline in use uses extended session info that needs
415 * traffic inspection. */
416 bool extended_session_info_in_use() const;
417
418 /** Check if routing guideline in use uses random value generated per session.
419 */
420 bool session_rand_used() const;
421
422 /** Check if the routing guidelines were updated. That means that there is a
423 * custom routing guideline in use instead of an auto-generated one.*/
424 bool routing_guidelines_updated() const;
425
426 /**
427 * Restore auto-generated guideline (based on Router's configuration).
428 *
429 * @return names of guidelines routes that were affected by this update.
430 */
432
433 /**
434 * Set the default guideline (auto-generated based on Router's
435 * configuration).
436 *
437 * @param routing_guidelines_doc routing guidelines document
438 */
439 void set_default_routing_guidelines(std::string routing_guidelines_doc) {
440 default_routing_guidelines_doc_ = std::move(routing_guidelines_doc);
441 }
442
443 private:
444 /// Compute changes introduced by the new routing guidelines.
445 RouteChanges compare(const Routing_guidelines_engine &new_routing_guidelines);
446
447 struct Rpd;
448 std::unique_ptr<Rpd> rpd_;
449 rapidjson::Document routing_guidelines_document_;
451
453};
454
455} // namespace routing_guidelines
456
457#endif // ROUTER_SRC_ROUTING_GUIDELINES_INCLUDE_ROUTING_GUIDELINES_ROUTING_GUIDELINES_H_
static stdx::flags< StmtClassifier > classify(SqlLexer &&lexer, bool forbid_set_trackers)
Definition: classic_query_sender.cc:97
Definition: routing_guidelines.h:141
std::vector< std::string > errors_
Definition: routing_guidelines.h:148
Definition: routing_guidelines.cc:81
Routing guidelines engine.
Definition: routing_guidelines.h:172
std::unordered_map< std::string, net::ip::address > ResolveCache
Map with preprocessed resolved hostnames.
Definition: routing_guidelines.h:188
Routing_guidelines_engine(const Routing_guidelines_engine &)=delete
Routing_guidelines_engine(Routing_guidelines_engine &&rp)
Routing_guidelines_engine & operator=(Routing_guidelines_engine &&)
Routing_guidelines_engine & operator=(const Routing_guidelines_engine &)=delete
std::string default_routing_guidelines_doc_
Definition: routing_guidelines.h:450
std::unique_ptr< Rpd > rpd_
Definition: routing_guidelines.h:447
void set_default_routing_guidelines(std::string routing_guidelines_doc)
Set the default guideline (auto-generated based on Router's configuration).
Definition: routing_guidelines.h:439
rapidjson::Document routing_guidelines_document_
Definition: routing_guidelines.h:449
Header for compiler-dependent features.
#define MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(X)
Definition: my_compiler.h:247
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:277
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:278
Define rapidjson::SizeType to be std::uint64_t.
static mysql_service_status_t create(my_h_string *) noexcept
Definition: mysql_string_all_empty.cc:43
Definition: routing_guidelines_datatypes.h:31
constexpr char kUndefinedRole[]
Keyword meaning that the member/cluster role is undefined.
Definition: routing_guidelines.h:56
Definition: gcs_xcom_synode.h:64
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:33
required uint32 priority
Definition: replication_group_member_actions.proto:35
required uint64 version
Definition: replication_group_member_actions.proto:41
required bool enabled
Definition: replication_group_member_actions.proto:33
#define ROUTING_GUIDELINES_EXPORT
Definition: routing_guidelines_export.h:15
static int compare(size_t a, size_t b)
Function to compare two size_t integers for their relative order.
Definition: rpl_utility.cc:107
case opt name
Definition: sslopt-case.h:29
Information about hostnames that needs to be resolved.
Definition: routing_guidelines.h:153
IP_version
Definition: routing_guidelines.h:154
Resolve_host(std::string address_, IP_version ip_version_)
Definition: routing_guidelines.h:156
std::string address
Definition: routing_guidelines.h:161
auto operator<=>(const Resolve_host &) const =default
IP_version ip_version
Definition: routing_guidelines.h:162
Information about this Router instance.
Definition: routing_guidelines.h:59
std::string hostname
hostname where router is running
Definition: routing_guidelines.h:70
std::string bind_address
address on which router is listening
Definition: routing_guidelines.h:71
std::string route_name
name of the plugin which handles the connection
Definition: routing_guidelines.h:74
std::map< std::string, std::string, std::less<> > tags_t
Definition: routing_guidelines.h:62
std::string local_cluster
name of the local cluster
Definition: routing_guidelines.h:69
tags_t tags
an object containing user defined tags stored in the cluster metadata for that Router instance
Definition: routing_guidelines.h:72
std::string name
name of the Router instance
Definition: routing_guidelines.h:76
Result of destination classification.
Definition: routing_guidelines.h:342
std::vector< std::string > class_names
Definition: routing_guidelines.h:343
std::forward_list< std::string > errors
Definition: routing_guidelines.h:344
Type for names of Routes changed during routing guidelines document update.
Definition: routing_guidelines.h:324
std::string guideline_name
Definition: routing_guidelines.h:325
std::vector< std::string > affected_routes
Definition: routing_guidelines.h:326
std::string routing_strategy
Routing strategy used to select specific destinations within this group.
Definition: routing_guidelines.h:297
std::vector< std::string > destination_classes
References to destinations classified at specific classes.
Definition: routing_guidelines.h:294
auto operator<=>(const DestinationGroup &) const =default
DestinationGroup(std::vector< std::string > destination_classes_, std::string routing_strategy_, const uint64_t priority_)
Definition: routing_guidelines.h:285
Result of route classification.
Definition: routing_guidelines.h:332
std::forward_list< std::string > errors
Definition: routing_guidelines.h:336
std::vector< Route::DestinationGroup > destination_groups
Definition: routing_guidelines.h:334
std::optional< bool > connection_sharing_allowed
Definition: routing_guidelines.h:335
std::string route_name
Definition: routing_guidelines.h:333
Class representing routing guidelines route section entry.
Definition: routing_guidelines.h:282
std::vector< DestinationGroup > destination_groups
Destination groups used by the route.
Definition: routing_guidelines.h:314
std::string name
Name of the route.
Definition: routing_guidelines.h:310
std::unique_ptr< rpn::Expression > match
Matching criterion for the given route.
Definition: routing_guidelines.h:312
auto operator<=>(const Route &) const =default
std::optional< bool > connection_sharing_allowed
Connection sharing enabled flag.
Definition: routing_guidelines.h:316
Information about one server destination.
Definition: routing_guidelines.h:80
std::string uuid
@server_uuid of the server
Definition: routing_guidelines.h:85
std::string cluster_set_name
name of the ClusterSet the server belongs to
Definition: routing_guidelines.h:94
std::string label
hostname:port as in the metadata
Definition: routing_guidelines.h:81
std::string address
address of the server
Definition: routing_guidelines.h:82
std::string cluster_name
name of the cluster the server belongs to
Definition: routing_guidelines.h:92
std::string cluster_role
PRIMARY or REPLICA depending on the role of the cluster in the ClusterSet, empty string if not define...
Definition: routing_guidelines.h:95
std::string member_role
PRIMARY, SECONDARY or READ_REPLICA, as reported by GR, empty string if not defined.
Definition: routing_guidelines.h:87
std::map< std::string, std::string, std::less<> > tags
user defined tags stored in the cluster metadata for that Server instance
Definition: routing_guidelines.h:90
Information about incoming session.
Definition: routing_guidelines.h:103
std::string schema
default schema specified at connect time
Definition: routing_guidelines.h:110
std::map< std::string, std::string, std::less<> > connect_attrs
session connect attributes by name
Definition: routing_guidelines.h:109
std::string source_ip
IP address the session is connecting from.
Definition: routing_guidelines.h:106
std::string user
username the session is authenticated with
Definition: routing_guidelines.h:107
std::string target_ip
address of the Router the session is connected to
Definition: routing_guidelines.h:104
Information about query details.
Definition: routing_guidelines.h:117
std::string default_schema
schema currently active for the session
Definition: routing_guidelines.h:118
std::map< std::string, std::string, std::less<> > query_tags
query specific tags specified as a comment in the SQL statement ( e.g.
Definition: routing_guidelines.h:123
std::map< std::string, std::string, std::less<> > query_hints
query specific hints specified at the protocol level (see WL#12542)
Definition: routing_guidelines.h:126