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