MySQL 8.4.4
Source Code Documentation
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
mysql_routing.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 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 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,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License 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
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTING_MYSQLROUTING_INCLUDED
27#define ROUTING_MYSQLROUTING_INCLUDED
28
32
33/** @file
34 * @brief Defining the class MySQLRouting
35 *
36 * This file defines the main class `MySQLRouting` which is used to configure,
37 * start and manage a connection routing from clients and MySQL servers.
38 *
39 */
40
41#include <array>
42#include <atomic>
43#include <chrono>
44#include <map>
45#include <memory>
46#include <mutex>
47#include <stdexcept>
48
49#ifndef _WIN32
50#include <arpa/inet.h>
51#include <netdb.h>
52#include <netinet/in.h>
53#include <netinet/tcp.h>
54#include <sys/socket.h>
55#include <unistd.h>
56#else
57#include <windows.h>
58#include <winsock2.h>
59#include <ws2tcpip.h>
60#endif
61
62#include "connection.h"
64#include "context.h"
65#include "destination.h"
71#include "mysql/harness/plugin.h"
73#include "mysql_router_thread.h"
74#include "mysql_routing_base.h"
77#include "mysqlrouter/routing.h"
79#include "mysqlrouter/uri.h"
80#include "plugin_config.h"
81#include "socket_container.h"
82#include "tcp_address.h"
83
84namespace mysql_harness {
85class PluginFuncEnv;
86} // namespace mysql_harness
87
88struct Nothing {};
89class MySQLRouting;
90
92 public:
94 const std::string &parent_routing_name)
95 : io_ctx_(io_ctx), parent_routing_name_(parent_routing_name) {}
96
98
101 virtual bool is_open() const = 0;
102
103 virtual void start(MySQLRouting *r, std::list<IoThread> &,
104 WaitableMonitor<Nothing> &waitable) = 0;
105
106 virtual std::string name() = 0;
107
109
110 protected:
112 // used when the acceptor logs
114};
115
117 public:
119 const std::string &parent_routing_name,
120 const std::string &address, uint16_t port);
121
124 bool is_open() const override;
125
126 void start(MySQLRouting *r, std::list<IoThread> &,
127 WaitableMonitor<Nothing> &waitable) override;
128
129 std::string name() override;
130
131 private:
134
135 std::string address_;
136 uint16_t port_;
137};
138
139#ifndef _WIN32
141 public:
143 const std::string &parent_routing_name,
144 const std::string &socket_name);
145
148 bool is_open() const override;
149
150 void start(MySQLRouting *r, std::list<IoThread> &,
151 WaitableMonitor<Nothing> &waitable) override;
152
153 std::string name() override;
154
155 private:
158
159 std::string socket_name_;
160};
161#endif
162
163/** @class MySQLRouting
164 * @brief Manage Connections from clients to MySQL servers
165 *
166 * The class MySQLRouter is used to start a service listening on a particular
167 * TCP port for incoming MySQL Client connection and route these to a MySQL
168 * Server.
169 */
171 public:
172 /** @brief Default constructor
173 *
174 * @param routing_config routing configuration
175 * @param io_ctx IO context
176 * @param route_name Name of connection routing (can be empty string)
177 * @param client_ssl_ctx SSL context of the client side
178 * @param dest_ssl_ctx SSL contexts of the destinations
179 */
180 MySQLRouting(const RoutingConfig &routing_config, net::io_context &io_ctx,
181 const std::string &route_name = {},
182 TlsServerContext *client_ssl_ctx = nullptr,
183 DestinationTlsContext *dest_ssl_ctx = nullptr);
184
185 /** @brief Runs the service and accept incoming connections
186 *
187 * Runs the connection routing service and starts accepting incoming
188 * MySQL client connections.
189 *
190 * @throw std::runtime_error on errors.
191 *
192 */
194
195 /** @brief Sets the destinations from URI
196 *
197 * Sets destinations using the given string. The string should be a comma
198 * separated list of MySQL servers.
199 *
200 * Example of destinations:
201 * "10.0.10.5,10.0.11.6:3307"
202 *
203 * @param csv destinations as comma-separated-values
204 */
205 void set_destinations_from_csv(const std::string &csv);
206
207 void set_destinations_from_uri(const mysqlrouter::URI &uri);
208
209 /** @brief Returns timeout when connecting to destination
210 *
211 * @return Timeout in seconds as int
212 */
213 std::chrono::milliseconds get_destination_connect_timeout() const noexcept {
214 return context_.get_destination_connect_timeout();
215 }
216
217 /** @brief Sets timeout when connecting to destination
218 *
219 * Checks timeout connecting with destination servers.
220 *
221 * @throw std::invalid_argument when an invalid value was provided.
222 *
223 * @param timeout Timeout
224 */
225 void validate_destination_connect_timeout(std::chrono::milliseconds timeout);
226
227 /** @brief Sets maximum active connections
228 *
229 * Sets maximum of active connections. Maximum must be between 1 and
230 * 65535.
231 *
232 * @throw std::invalid_argument when an invalid value was provided.
233 *
234 * @param maximum Max number of connections allowed
235 * @return New value as int
236 */
237 int set_max_connections(int maximum);
238
239 /** @brief Returns maximum active connections
240 *
241 * @return Maximum as int
242 */
243 int get_max_connections() const noexcept override { return max_connections_; }
244
245 /**
246 * create new connection to MySQL Server than can handle client's
247 * traffic and adds it to connection container.
248 *
249 * @param client_socket socket used to transfer data to/from client
250 * @param client_endpoint endpoint of client
251 */
252 template <class ClientProtocol>
253 void create_connection(
254 typename ClientProtocol::socket client_socket,
255 const typename ClientProtocol::endpoint &client_endpoint);
256
258
259 std::vector<mysql_harness::TCPAddress> get_destinations() const override;
260
261 std::vector<MySQLRoutingAPI::ConnData> get_connections() override;
262
263 MySQLRoutingConnectionBase *get_connection(const std::string &) override;
264
265 RouteDestination *destinations() { return destination_.get(); }
266
267 void disconnect_all();
268
269 /**
270 * Stop accepting new connections on a listening socket.
271 */
272 void stop_socket_acceptors() override;
273
274 /**
275 * Check if we are accepting connections on a routing socket.
276 *
277 * @retval true if we are accepting connections, false otherwise
278 */
279 bool is_accepting_connections() const override;
280
281 /**
282 * Start accepting new connections on a listening socket
283 *
284 * @returns std::string on errors.
285 */
286 stdx::expected<void, std::string> start_accepting_connections() override;
287
288 /**
289 * Start accepting new connections on a listening socket after it has been
290 * quarantined for lack of valid destinations
291 *
292 * @returns std::string on errors.
293 */
294 stdx::expected<void, std::string> restart_accepting_connections() override;
295
296 private:
297 /** @brief Sets unix socket permissions so that the socket is accessible
298 * to all users (no-op on Windows)
299 * @param socket_file path to socket file
300 *
301 * @throw std::runtime_error if chmod() inside fails
302 */
303 static void set_unix_socket_permissions(const char *socket_file);
304
307
308 public:
309 MySQLRoutingContext &get_context() override { return context_; }
310
311 bool is_running() const override { return is_running_; }
312
313 /**
314 * get the purpose of connections to this route.
315 *
316 * - read-write : all statements are treated as "read-write".
317 * - read-only : all statements are treated as "read-only".
318 * - unavailable: it is currently unknown where the statement should go to.
319 *
320 * "Unavailable" is used for read-write splitting where the purpose is
321 * determined per statement, session, ...
322 *
323 * A statement over a read-only server connection may end up on a read-write
324 * server in case all read-only servers aren't reachable. Even if the server
325 * is read-write, the connections purpose is read-only and if the server
326 * changes its role from PRIMARY to SECONDARY, these read-only connections
327 * will not be abort as a SECONDARY is good enough to serve read-only
328 * connections.
329 */
330 mysqlrouter::ServerMode purpose() const override;
331
332 private:
333 /** Monitor for notifying socket acceptor */
334 WaitableMonitor<Nothing> acceptor_waitable_{Nothing{}};
335
336 /** @brief wrapper for data used by all connections */
338
340
341 /** @brief Destination object to use when getting next connection */
342 std::unique_ptr<RouteDestination> destination_;
343
344 bool is_destination_standalone_{false};
345
346 /** @brief Routing strategy to use when getting next destination */
348
349 /** @brief access_mode of the servers in the routing */
351
352 /** @brief Maximum active connections
353 *
354 * Maximum number of incoming connections that will be accepted
355 * by this MySQLRouter instances. There is no maximum for outgoing
356 * connections since it is one-to-one with incoming.
357 */
359
360 /** @brief used to unregister from subscription on allowed nodes changes */
362
363 /** @brief container for connections */
365
366 /** Information if the routing plugin is still running. */
367 std::atomic<bool> is_running_{true};
368
369 /** Used when the accepting port is been reopened and it failed, to schedule
370 * another retry for standalone-destination(s) route. */
371 net::steady_timer accept_port_reopen_retry_timer_{io_ctx_};
372
373#ifdef FRIEND_TEST
374 FRIEND_TEST(RoutingTests, bug_24841281);
375 FRIEND_TEST(RoutingTests, get_routing_thread_name);
376 FRIEND_TEST(ClassicProtocolRoutingTest, NoValidDestinations);
377 FRIEND_TEST(TestSetupTcpService, single_addr_ok);
378 FRIEND_TEST(TestSetupTcpService, getaddrinfo_fails);
379 FRIEND_TEST(TestSetupTcpService, socket_fails_for_all_addr);
380 FRIEND_TEST(TestSetupTcpService, socket_fails);
381 FRIEND_TEST(TestSetupTcpService, bind_fails);
382 FRIEND_TEST(TestSetupTcpService, listen_fails);
383#ifndef _WIN32
384 FRIEND_TEST(TestSetupTcpService, setsockopt_fails);
385 FRIEND_TEST(TestSetupNamedSocketService, unix_socket_permissions_failure);
386#endif
387#endif
388
389 std::vector<std::unique_ptr<AcceptingEndpoint>> accepting_endpoints_;
390};
391
392extern "C" {
393extern mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing;
394}
395
396#endif // ROUTING_MYSQLROUTING_INCLUDED
Definition: mysql_routing.h:116
std::string address_
Definition: mysql_routing.h:135
uint16_t port_
Definition: mysql_routing.h:136
net::ip::tcp::acceptor service_
Definition: mysql_routing.h:132
net::ip::tcp::endpoint service_endpoint_
Definition: mysql_routing.h:133
Definition: mysql_routing.h:140
local::stream_protocol::acceptor service_
Definition: mysql_routing.h:156
std::string socket_name_
Definition: mysql_routing.h:159
local::stream_protocol::endpoint service_endpoint_
Definition: mysql_routing.h:157
Definition: mysql_routing.h:91
virtual ~AcceptingEndpoint()
Definition: mysql_routing.h:108
virtual stdx::expected< void, std::error_code > setup()=0
virtual void start(MySQLRouting *r, std::list< IoThread > &, WaitableMonitor< Nothing > &waitable)=0
virtual std::string name()=0
std::string parent_routing_name_
Definition: mysql_routing.h:113
net::io_context & io_ctx_
Definition: mysql_routing.h:111
AcceptingEndpoint(const AcceptingEndpoint &)=delete
virtual bool is_open() const =0
AcceptingEndpoint(net::io_context &io_ctx, const std::string &parent_routing_name)
Definition: mysql_routing.h:93
virtual stdx::expected< void, std::error_code > cancel()=0
container for connections to MySQL Server.
Definition: connection_container.h:167
TlsClientContext per destination.
Definition: destination_ssl_context.h:42
Facade to avoid a tight coupling between Routing component and actual routing endpoint implementation...
Definition: mysql_routing_base.h:41
Definition: connection.h:44
MySQLRoutingContext holds data used by MySQLRouting (1 per plugin instances) and MySQLRoutingConnecti...
Definition: context.h:59
Manage Connections from clients to MySQL servers.
Definition: mysql_routing.h:170
std::chrono::milliseconds get_destination_connect_timeout() const noexcept
Returns timeout when connecting to destination.
Definition: mysql_routing.h:213
std::unique_ptr< RouteDestination > destination_
Destination object to use when getting next connection.
Definition: mysql_routing.h:342
MySQLRoutingContext & get_context() override
Definition: mysql_routing.h:309
ConnectionContainer connection_container_
container for connections
Definition: mysql_routing.h:364
routing::AccessMode access_mode_
access_mode of the servers in the routing
Definition: mysql_routing.h:350
AllowedNodesChangeCallbacksListIterator allowed_nodes_list_iterator_
used to unregister from subscription on allowed nodes changes
Definition: mysql_routing.h:361
std::vector< std::unique_ptr< AcceptingEndpoint > > accepting_endpoints_
Definition: mysql_routing.h:389
MySQLRoutingContext context_
wrapper for data used by all connections
Definition: mysql_routing.h:337
net::io_context & io_ctx_
Definition: mysql_routing.h:339
RouteDestination * destinations()
Definition: mysql_routing.h:265
int max_connections_
Maximum active connections.
Definition: mysql_routing.h:358
bool is_running() const override
Definition: mysql_routing.h:311
int get_max_connections() const noexcept override
Returns maximum active connections.
Definition: mysql_routing.h:243
routing::RoutingStrategy routing_strategy_
Routing strategy to use when getting next destination.
Definition: mysql_routing.h:347
Manage destinations for a Connection Routing.
Definition: destination.h:189
virtual mysql_harness::TCPAddress get(const std::string &address, uint16_t port)
Gets destination based on address and port.
Definition: destination.cc:131
route specific configuration.
Definition: routing_config.h:40
TLS Context for the server side.
Definition: tls_server_context.h:51
Monitor can be waited for.
Definition: monitor.h:62
PluginFuncEnv object.
Definition: loader.h:673
Parse and create URIs according to RFC3986.
Definition: uri.h:70
Definition: socket.h:1293
Definition: timer.h:57
Definition: io_context.h:61
Definition: internet.h:678
Definition: expected.h:286
static int get_connection(MEM_ROOT *mem_root, FEDERATED_SHARE *share)
Definition: ha_federated.cc:608
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:180
static void run(mysql_harness::PluginFuncEnv *)
Definition: io_plugin.cc:197
mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing
Definition: routing_plugin.cc:591
std::string get_routing_thread_name(const std::string &config_name, const std::string &prefix)
return a short string suitable to be used as a thread name
Definition: mysql_routing_common.cc:30
static bool timeout(bool(*wait_condition)())
Timeout function.
Definition: log0meb.cc:498
Definition: common.h:42
ServerMode
Definition: datatypes.h:50
stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol)
Definition: socket.h:63
RoutingStrategy get_routing_strategy(const std::string &value)
Returns RoutingStrategy for its literal representation.
Definition: routing.cc:87
AccessMode
Definition: routing.h:259
RoutingStrategy
Routing strategies supported by Routing plugin.
Definition: routing.h:265
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:33
#define ROUTING_EXPORT
Definition: routing_export.h:15
#define ROUTING_PLUGIN_EXPORT
Definition: routing_plugin_export.h:15
AllowedNodesChangeCallbacksList::iterator AllowedNodesChangeCallbacksListIterator
Definition: destination.h:65
case opt name
Definition: sslopt-case.h:29
Definition: mysql_routing.h:88