MySQL 8.0.29
Source Code Documentation
mysql_routing.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 2022, 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,
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 included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef ROUTING_MYSQLROUTING_INCLUDED
26#define ROUTING_MYSQLROUTING_INCLUDED
27
30
31/** @file
32 * @brief Defining the class MySQLRouting
33 *
34 * This file defines the main class `MySQLRouting` which is used to configure,
35 * start and manage a connection routing from clients and MySQL servers.
36 *
37 */
38
39#include <array>
40#include <atomic>
41#include <iostream>
42#include <map>
43#include <memory>
44#include <mutex>
45#include <stdexcept>
46
47#ifndef _WIN32
48#include <arpa/inet.h>
49#include <netdb.h>
50#include <netinet/in.h>
51#include <netinet/tcp.h>
52#include <sys/socket.h>
53#include <unistd.h>
54#else
55#include <windows.h>
56#include <winsock2.h>
57#include <ws2tcpip.h>
58#endif
59
60#include "connection.h"
62#include "context.h"
63#include "destination.h"
69#include "mysql/harness/plugin.h"
71#include "mysql_router_thread.h"
72#include "mysql_routing_base.h"
73#include "mysqlrouter/routing.h"
76#include "mysqlrouter/uri.h"
77#include "plugin_config.h"
79#include "socket_container.h"
80#include "ssl_mode.h"
81#include "tcp_address.h"
82
83namespace mysql_harness {
84class PluginFuncEnv;
85}
86
87struct Nothing {};
88
89/** @class MySQLRouting
90 * @brief Manage Connections from clients to MySQL servers
91 *
92 * The class MySQLRouter is used to start a service listening on a particular
93 * TCP port for incoming MySQL Client connection and route these to a MySQL
94 * Server.
95 *
96 * Connection routing will not analyze or parse any MySQL package (except from
97 * those in the handshake phase to be able to discover invalid connection
98 * error) nor will it do any authentication. It will not handle errors from the
99 * MySQL server and not automatically recover. The client communicate through
100 * MySQL Router just like it would directly connecting.
101 *
102 * The MySQL Server is chosen from a given list of hosts or IP addresses
103 * (with or without TCP port) based on the the mode. For example, mode
104 * read-only will go through the list of servers in a round-robin way. The
105 * mode read-write will always go through the list from the beginning and
106 * failover to the next available.
107 *
108 *
109 * Example usage: bind to all IP addresses and use TCP Port 7001
110 *
111 * MySQLRouting r(routing::AccessMode::kReadWrite, "0.0.0.0", 7001);
112 * r.destination_connect_timeout = std::chrono::seconds(1);
113 * r.set_destinations_from_csv("10.0.10.5;10.0.11.6");
114 * r.start();
115 *
116 * The above example will, when MySQL running on 10.0.10.5 is not available,
117 * use 10.0.11.6 to setup the connection routing.
118 *
119 */
121 public:
122 /** @brief Default constructor
123 *
124 * @param io_ctx IO context
125 * @param routing_strategy routing strategy
126 * @param port TCP port for listening for incoming connections
127 * @param protocol protocol for the routing
128 * @param access_mode access mode of the servers
129 * @param bind_address bind_address Bind to particular IP address
130 * @param named_socket Bind to Unix socket/Windows named pipe
131 * @param route_name Name of connection routing (can be empty string)
132 * @param max_connections Maximum allowed active connections
133 * @param destination_connect_timeout Timeout trying to connect destination
134 * server
135 * @param max_connect_errors Maximum connect or handshake errors per host
136 * @param connect_timeout Timeout waiting for handshake response
137 * @param net_buffer_length send/receive buffer size
138 * @param client_ssl_mode SSL mode of the client side
139 * @param client_ssl_ctx SSL context of the client side
140 * @param server_ssl_mode SSL mode of the serer side
141 * @param dest_ssl_ctx SSL contexts of the destinations
142 */
145 uint16_t port, const Protocol::Type protocol,
147 const std::string &bind_address = {"0.0.0.0"},
148 const mysql_harness::Path &named_socket = mysql_harness::Path(),
149 const std::string &route_name = {},
151 std::chrono::milliseconds destination_connect_timeout =
154 std::chrono::milliseconds connect_timeout =
156 unsigned int net_buffer_length = routing::kDefaultNetBufferLength,
157 SslMode client_ssl_mode = SslMode::kDisabled,
158 TlsServerContext *client_ssl_ctx = nullptr,
159 SslMode server_ssl_mode = SslMode::kDisabled,
160 DestinationTlsContext *dest_ssl_ctx = nullptr);
161
162 /** @brief Starts the service and accept incoming connections
163 *
164 * Starts the connection routing service and start accepting incoming
165 * MySQL client connections. Each connection will be further handled
166 * in a separate thread.
167 *
168 * @throw std::runtime_error on errors.
169 *
170 */
172
173 /** @brief Sets the destinations from URI
174 *
175 * Sets destinations using the given string and the given mode. The string
176 * should be a comma separated list of MySQL servers.
177 *
178 * The mode is one of MySQLRouting::Mode, for example
179 * MySQLRouting::Mode::kReadOnly.
180 *
181 * Example of destinations:
182 * "10.0.10.5,10.0.11.6:3307"
183 *
184 * @param csv destinations as comma-separated-values
185 */
186 void set_destinations_from_csv(const std::string &csv);
187
188 void set_destinations_from_uri(const mysqlrouter::URI &uri);
189
190 /** @brief Returns timeout when connecting to destination
191 *
192 * @return Timeout in seconds as int
193 */
194 std::chrono::milliseconds get_destination_connect_timeout() const noexcept {
195 return context_.get_destination_connect_timeout();
196 }
197
198 /** @brief Sets timeout when connecting to destination
199 *
200 * Checks timeout connecting with destination servers.
201 *
202 * @throw std::invalid_argument when an invalid value was provided.
203 *
204 * @param timeout Timeout
205 */
206 void validate_destination_connect_timeout(std::chrono::milliseconds timeout);
207
208 /** @brief Sets maximum active connections
209 *
210 * Sets maximum of active connections. Maximum must be between 1 and
211 * 65535.
212 *
213 * @throw std::invalid_argument when an invalid value was provided.
214 *
215 * @param maximum Max number of connections allowed
216 * @return New value as int
217 */
218 int set_max_connections(int maximum);
219
220 /** @brief Returns maximum active connections
221 *
222 * @return Maximum as int
223 */
224 int get_max_connections() const noexcept override { return max_connections_; }
225
226 /**
227 * create new connection to MySQL Server than can handle client's
228 * traffic and adds it to connection container.
229 *
230 * @param client_socket socket used to transfer data to/from client
231 * @param client_endpoint endpoint of client
232 */
233 template <class ClientProtocol>
234 void create_connection(
235 typename ClientProtocol::socket client_socket,
236 const typename ClientProtocol::endpoint &client_endpoint);
237
239
240 routing::AccessMode get_mode() const override;
241
242 std::vector<mysql_harness::TCPAddress> get_destinations() const override;
243
244 std::vector<MySQLRoutingAPI::ConnData> get_connections() override;
245
246 RouteDestination *destinations() { return destination_.get(); }
247
248 net::ip::tcp::acceptor &tcp_socket() { return service_tcp_; }
249
250 void disconnect_all();
251
252 /**
253 * Stop accepting new connections on a listening socket.
254 */
255 void stop_socket_acceptors() override;
256
257 /**
258 * Check if we are accepting connections on a routing socket.
259 *
260 * @retval true if we are accepting connections, false otherwise
261 */
262 bool is_accepting_connections() const override;
263
264 /**
265 * Start accepting new connections on a listening socket
266 *
267 * @returns std::error_code on errors.
268 */
270
271 private:
272 /**
273 * Get listening socket detail information used for the logging purposes.
274 */
275 std::string get_port_str() const;
276
277 /** @brief Sets up the TCP service
278 *
279 * Sets up the TCP service binding to IP addresses and TCP port.
280 *
281 * @returns std::error_code on errors.
282 */
283 stdx::expected<void, std::error_code> setup_tcp_service();
284
285 /** @brief Sets up the named socket service
286 *
287 * Sets up the named socket service creating a socket file on UNIX systems.
288 *
289 * @returns std::error_code on errors.
290 */
291 stdx::expected<void, std::error_code> setup_named_socket_service();
292
293 /** @brief Sets unix socket permissions so that the socket is accessible
294 * to all users (no-op on Windows)
295 * @param socket_file path to socket file
296 *
297 * @throw std::runtime_error if chmod() inside fails
298 */
299 static void set_unix_socket_permissions(const char *socket_file);
300
303
304 public:
305 MySQLRoutingContext &get_context() override { return context_; }
306
307 bool is_running() const override { return is_running_; }
308
309 private:
310 /** Monitor for notifying socket acceptor */
311 WaitableMonitor<Nothing> acceptor_waitable_{Nothing{}};
312
313 /** @brief wrapper for data used by all connections */
315
317
318 /** @brief Destination object to use when getting next connection */
319 std::unique_ptr<RouteDestination> destination_;
320
321 bool is_destination_standalone_{false};
322
323 /** @brief Routing strategy to use when getting next destination */
325
326 /** @brief Access mode of the servers in the routing */
328
329 /** @brief Maximum active connections
330 *
331 * Maximum number of incoming connections that will be accepted
332 * by this MySQLRouter instances. There is no maximum for outgoing
333 * connections since it is one-to-one with incoming.
334 */
336
337 /** @brief Socket descriptor of the TCP service */
340
341#if !defined(_WIN32)
342 /** @brief Socket descriptor of the named socket service */
345#endif
346
347 /** @brief used to unregister from subscription on allowed nodes changes */
349
350 /** @brief container for connections */
352
353 /** Information if the routing plugging is still running. */
354 std::atomic<bool> is_running_{true};
355
356 /** Tracking information about connections that are pending and are not yet
357 * established. */
358 WaitableMonitor<uint64_t> pending_connections_counter_{0};
359
360#ifdef FRIEND_TEST
361 FRIEND_TEST(RoutingTests, bug_24841281);
362 FRIEND_TEST(RoutingTests, get_routing_thread_name);
363 FRIEND_TEST(ClassicProtocolRoutingTest, NoValidDestinations);
364 FRIEND_TEST(TestSetupTcpService, single_addr_ok);
365 FRIEND_TEST(TestSetupTcpService, getaddrinfo_fails);
366 FRIEND_TEST(TestSetupTcpService, socket_fails_for_all_addr);
367 FRIEND_TEST(TestSetupTcpService, socket_fails);
368 FRIEND_TEST(TestSetupTcpService, bind_fails);
369 FRIEND_TEST(TestSetupTcpService, listen_fails);
370#ifndef _WIN32
371 FRIEND_TEST(TestSetupTcpService, setsockopt_fails);
372 FRIEND_TEST(TestSetupNamedSocketService, unix_socket_permissions_failure);
373#endif
374#endif
375};
376
377extern "C" {
378extern mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing;
379}
380
381#endif // ROUTING_MYSQLROUTING_INCLUDED
Type
supported protocols
Definition: base_protocol.h:31
container for connections to MySQL Server.
Definition: connection_container.h:166
TlsClientContext per destination.
Definition: destination_ssl_context.h:40
Facade to avoid a tight coupling between Routing component and actual routing endpoint implementation...
Definition: mysql_routing_base.h:40
virtual routing::AccessMode get_mode() const =0
virtual std::vector< mysql_harness::TCPAddress > get_destinations() const =0
virtual void stop_socket_acceptors()=0
virtual routing::RoutingStrategy get_routing_strategy() const =0
virtual bool is_accepting_connections() const =0
virtual stdx::expected< void, std::error_code > start_accepting_connections()=0
virtual std::vector< MySQLRoutingAPI::ConnData > get_connections()=0
MySQLRoutingContext holds data used by MySQLRouting (1 per plugin instances) and MySQLRoutingConnecti...
Definition: context.h:57
Manage Connections from clients to MySQL servers.
Definition: mysql_routing.h:120
std::chrono::milliseconds get_destination_connect_timeout() const noexcept
Returns timeout when connecting to destination.
Definition: mysql_routing.h:194
std::unique_ptr< RouteDestination > destination_
Destination object to use when getting next connection.
Definition: mysql_routing.h:319
local::stream_protocol::acceptor service_named_socket_
Socket descriptor of the named socket service.
Definition: mysql_routing.h:343
net::ip::tcp::acceptor service_tcp_
Socket descriptor of the TCP service.
Definition: mysql_routing.h:338
MySQLRoutingContext & get_context() override
Definition: mysql_routing.h:305
ConnectionContainer connection_container_
container for connections
Definition: mysql_routing.h:351
routing::AccessMode access_mode_
Access mode of the servers in the routing.
Definition: mysql_routing.h:327
AllowedNodesChangeCallbacksListIterator allowed_nodes_list_iterator_
used to unregister from subscription on allowed nodes changes
Definition: mysql_routing.h:348
MySQLRoutingContext context_
wrapper for data used by all connections
Definition: mysql_routing.h:314
net::io_context & io_ctx_
Definition: mysql_routing.h:316
RouteDestination * destinations()
Definition: mysql_routing.h:246
int max_connections_
Maximum active connections.
Definition: mysql_routing.h:335
local::stream_protocol::endpoint service_named_endpoint_
Definition: mysql_routing.h:344
net::ip::tcp::acceptor & tcp_socket()
Definition: mysql_routing.h:248
bool is_running() const override
Definition: mysql_routing.h:307
int get_max_connections() const noexcept override
Returns maximum active connections.
Definition: mysql_routing.h:224
net::ip::tcp::endpoint service_tcp_endpoint_
Definition: mysql_routing.h:339
routing::RoutingStrategy routing_strategy_
Routing strategy to use when getting next destination.
Definition: mysql_routing.h:324
Manage destinations for a Connection Routing.
Definition: destination.h:196
virtual mysql_harness::TCPAddress get(const std::string &address, uint16_t port)
Gets destination based on address and port.
Definition: destination.cc:129
TLS Context for the server side.
Definition: tls_server_context.h:45
Monitor can be waited for.
Definition: monitor.h:61
Class representing a path in a file system.
Definition: filesystem.h:61
PluginFuncEnv object.
Definition: loader.h:674
Parse and create URIs according to RFC3986.
Definition: uri.h:69
Definition: socket.h:1408
Definition: io_context.h:59
Definition: internet.h:677
Definition: expected.h:936
static void start(mysql_harness::PluginFuncEnv *env)
Definition: http_auth_backend_plugin.cc:168
static std::unique_ptr< net::io_context > io_ctx
Definition: io_plugin.cc:104
mysql_harness::Plugin ROUTING_PLUGIN_EXPORT harness_plugin_routing
Definition: routing_plugin.cc:460
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:29
ulong max_connections
Definition: mysqld.cc:1352
ulong connect_timeout
Definition: mysqld.cc:1311
ulong max_connect_errors
Definition: mysqld.cc:1352
static bool timeout(bool(*wait_condition)())
Timeout function.
Definition: log0meb.cc:493
Definition: common.h:41
stdx::expected< native_handle_type, error_type > socket(int family, int sock_type, int protocol)
Definition: socket.h:56
constexpr const unsigned long long kDefaultMaxConnectErrors
Maximum connect or handshake errors per host.
Definition: routing.h:66
AccessMode
Modes supported by Routing plugin.
Definition: routing.h:97
RoutingStrategy
Routing strategies supported by Routing plugin.
Definition: routing.h:104
constexpr const std::chrono::seconds kDefaultClientConnectTimeout
Timeout waiting for handshake response from client.
Definition: routing.h:87
constexpr const std::chrono::seconds kDefaultDestinationConnectionTimeout
Timeout connecting to destination (in seconds).
Definition: routing.h:57
constexpr const unsigned int kDefaultNetBufferLength
Default net buffer length.
Definition: routing.h:79
constexpr const int kDefaultMaxConnections
Max number of active routes for this routing instance.
Definition: routing.h:50
required uint64 port
Definition: replication_asynchronous_connection_failover.proto:32
#define ROUTING_EXPORT
Definition: routing_export.h:15
#define ROUTING_PLUGIN_EXPORT
Definition: routing_plugin_export.h:15
AllowedNodesChangeCallbacksList::iterator AllowedNodesChangeCallbacksListIterator
Definition: destination.h:72
SslMode
Definition: ssl_mode.h:28
Definition: mysql_routing.h:87