-
Notifications
You must be signed in to change notification settings - Fork 994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for AWS RDS MySQL Multi-AZ Cluster auto-discovery #4406
Changes from 5 commits
5a30377
bb35b20
0bcddd0
d04173b
e0db02d
bbb6176
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,9 @@ struct cmp_str { | |
|
||
#define N_L_ASE 16 | ||
|
||
#define AWS_ENDPOINT_SUFFIX_STRING "rds.amazonaws.com" | ||
#define QUERY_READ_ONLY_AND_AWS_TOPOLOGY_DISCOVERY "SELECT @@global.read_only read_only, id, endpoint, port from mysql.rds_topology" | ||
|
||
/* | ||
|
||
Implementation of monitoring in AWS Aurora will be different than previous modules | ||
|
@@ -197,7 +200,8 @@ enum MySQL_Monitor_State_Data_Task_Type { | |
MON_GROUP_REPLICATION, | ||
MON_REPLICATION_LAG, | ||
MON_GALERA, | ||
MON_AWS_AURORA | ||
MON_AWS_AURORA, | ||
MON_READ_ONLY__AND__AWS_RDS_TOPOLOGY_DISCOVERY | ||
}; | ||
|
||
enum class MySQL_Monitor_State_Data_Task_Result { | ||
|
@@ -229,6 +233,7 @@ class MySQL_Monitor_State_Data { | |
char *hostname; | ||
int port; | ||
int writer_hostgroup; // used only by group replication | ||
int reader_hostgroup; | ||
bool writer_is_also_reader; // used only by group replication | ||
int max_transactions_behind; // used only by group replication | ||
int max_transactions_behind_count; // used only by group replication | ||
|
@@ -442,6 +447,7 @@ class MySQL_Monitor { | |
static bool update_dns_cache_from_mysql_conn(const MYSQL* mysql); | ||
static void trigger_dns_cache_update(); | ||
|
||
void process_discovered_topology(const std::string& originating_server_hostname, vector<MYSQL_ROW> discovered_servers, int reader_hostgroup); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even if |
||
|
||
private: | ||
std::vector<table_def_t *> *tables_defs_monitor; | ||
|
@@ -553,7 +559,7 @@ class MySQL_Monitor { | |
* Note: Calling init_async is mandatory before executing tasks asynchronously. | ||
*/ | ||
void monitor_ping_async(SQLite3_result* resultset); | ||
void monitor_read_only_async(SQLite3_result* resultset); | ||
void monitor_read_only_async(SQLite3_result* resultset, bool do_discovery_check); | ||
void monitor_replication_lag_async(SQLite3_result* resultset); | ||
void monitor_group_replication_async(); | ||
void monitor_galera_async(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2200,6 +2200,7 @@ bool MySQL_HostGroups_Manager::commit( | |
// fill Hostgroup_Manager_Mapping with latest records | ||
update_hostgroup_manager_mappings(); | ||
|
||
|
||
ev_async_send(gtid_ev_loop, gtid_ev_async); | ||
|
||
__sync_fetch_and_add(&status.servers_table_version,1); | ||
|
@@ -8253,6 +8254,119 @@ void MySQL_HostGroups_Manager::HostGroup_Server_Mapping::remove_HGM(MySrvC* srv) | |
srv->ConnectionsFree->drop_all_connections(); | ||
} | ||
|
||
/** | ||
* @brief Updates replication hostgroups by adding autodiscovered mysql servers. | ||
* @details Adds each server from 'new_servers' to the 'runtime_mysql_servers' table. | ||
* We then rebuild the 'mysql_servers' table as well as the internal 'hostname_hostgroup_mapping'. | ||
* @param new_servers A vector of tuples where each tuple contains the values needed to add each new server. | ||
* | ||
* @return Returns EXIT_FAILURE code on failure and EXIT_SUCCESS code on success. | ||
*/ | ||
int MySQL_HostGroups_Manager::add_discovered_servers_to_mysql_servers_and_replication_hostgroups(vector<tuple<string, int, int>> new_servers) { | ||
int exit_code = EXIT_SUCCESS; | ||
bool added_new_server = false; | ||
wrlock(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing lock on Admin |
||
|
||
try { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See comment when the function is called about error handling. |
||
for (tuple<string, int, int> s : new_servers) { | ||
string host = std::get<0>(s); | ||
uint16_t port = std::get<1>(s); | ||
long int hostgroup_id = std::get<2>(s); | ||
|
||
// Add the discovered server with default values | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a newer abstraction that can be used for server placement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, I will make use of the new abstraction. For the third field of |
||
MySrvC* mysrvc = new MySrvC( | ||
const_cast<char*>(host.c_str()), port, 0, 1, MYSQL_SERVER_STATUS_ONLINE, 0, -1, 0, -1, 0, const_cast<char*>("Discovered endpoint") | ||
); | ||
add(mysrvc, hostgroup_id); | ||
|
||
proxy_info( | ||
"Adding new discovered server %s:%d with: hostgroup=%d, weight=%ld, max_connections=%ld, use_ssl=%d\n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The following There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removing this logging statement here as |
||
host.c_str(), port, hostgroup_id, mysrvc->weight, mysrvc->max_connections, mysrvc->use_ssl | ||
); | ||
|
||
added_new_server = true; | ||
} | ||
|
||
if (added_new_server) { | ||
purge_mysql_servers_table(); | ||
mydb->execute("DELETE FROM mysql_servers"); | ||
proxy_debug(PROXY_DEBUG_MYSQL_CONNPOOL, 4, "DELETE FROM mysql_servers\n"); | ||
generate_mysql_servers_table(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This block, starting at previous
Checksum re-computation is mandatory in this case after re-generating
The comments with |
||
update_table_mysql_servers_for_monitor(false); | ||
rebuild_hostname_hostgroup_mapping(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the previous suggested changes, this function should be replaced by There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deleting the new |
||
} | ||
} catch (...) { | ||
exit_code = EXIT_FAILURE; | ||
} | ||
|
||
wrunlock(); | ||
return exit_code; | ||
} | ||
|
||
/** | ||
* @brief Rebuilds the 'hostname_hostgroup_mapping' | ||
* @details Rebuilds the internal 'hostname_hostgroup_mapping' assuming new data has been entered | ||
* and calculates new checksums for 'mysql_servers' and 'mysql_replication_hostgroups'. | ||
*/ | ||
void MySQL_HostGroups_Manager::rebuild_hostname_hostgroup_mapping() { | ||
proxy_info("Rebuilding 'Hostgroup_Manager_Mapping' due to checksums change - mysql_servers { old: 0x%lX, new: 0x%lX }, mysql_replication_hostgroups { old:0x%lX, new:0x%lX }\n", | ||
hgsm_mysql_servers_checksum, table_resultset_checksum[HGM_TABLES::MYSQL_SERVERS], | ||
hgsm_mysql_replication_hostgroups_checksum, table_resultset_checksum[HGM_TABLES::MYSQL_REPLICATION_HOSTGROUPS]); | ||
|
||
char* error = NULL; | ||
int cols = 0; | ||
int affected_rows = 0; | ||
SQLite3_result* resultset = NULL; | ||
|
||
const char* query = "SELECT DISTINCT hostname, port, '1' is_writer, status, reader_hostgroup, writer_hostgroup, mem_pointer FROM mysql_replication_hostgroups JOIN mysql_servers ON hostgroup_id=writer_hostgroup WHERE status<>3 \ | ||
UNION \ | ||
SELECT DISTINCT hostname, port, '0' is_writer, status, reader_hostgroup, writer_hostgroup, mem_pointer FROM mysql_replication_hostgroups JOIN mysql_servers ON hostgroup_id=reader_hostgroup WHERE status<>3 \ | ||
ORDER BY hostname, port"; | ||
|
||
mydb->execute_statement(query, &error, &cols, &affected_rows, &resultset); | ||
|
||
hostgroup_server_mapping.clear(); | ||
|
||
if (resultset && resultset->rows_count) { | ||
std::string fetched_server_id; | ||
HostGroup_Server_Mapping* fetched_server_mapping = NULL; | ||
|
||
for (std::vector<SQLite3_row*>::iterator it = resultset->rows.begin(); it != resultset->rows.end(); it++) { | ||
SQLite3_row *r = *it; | ||
|
||
const std::string& server_id = std::string(r->fields[0]) + ":::" + r->fields[1]; | ||
|
||
if (fetched_server_mapping == NULL || server_id != fetched_server_id) { | ||
auto itr = hostgroup_server_mapping.find(server_id); | ||
|
||
if (itr == hostgroup_server_mapping.end()) { | ||
std::unique_ptr<HostGroup_Server_Mapping> server_mapping(new HostGroup_Server_Mapping(this)); | ||
fetched_server_mapping = server_mapping.get(); | ||
hostgroup_server_mapping.insert( std::pair<std::string,std::unique_ptr<MySQL_HostGroups_Manager::HostGroup_Server_Mapping>> { | ||
server_id, std::move(server_mapping) | ||
} ); | ||
} else { | ||
fetched_server_mapping = itr->second.get(); | ||
} | ||
|
||
fetched_server_id = server_id; | ||
} | ||
|
||
HostGroup_Server_Mapping::Node node; | ||
node.reader_hostgroup_id = atoi(r->fields[4]); | ||
node.writer_hostgroup_id = atoi(r->fields[5]); | ||
node.srv = reinterpret_cast<MySrvC*>(atoll(r->fields[6])); | ||
|
||
HostGroup_Server_Mapping::Type type = (r->fields[2] && r->fields[2][0] == '1') ? HostGroup_Server_Mapping::Type::WRITER : HostGroup_Server_Mapping::Type::READER; | ||
fetched_server_mapping->add(type, node); | ||
} | ||
} | ||
delete resultset; | ||
|
||
hgsm_mysql_servers_checksum = table_resultset_checksum[HGM_TABLES::MYSQL_SERVERS]; | ||
hgsm_mysql_replication_hostgroups_checksum = table_resultset_checksum[HGM_TABLES::MYSQL_REPLICATION_HOSTGROUPS]; | ||
} | ||
|
||
MySQLServers_SslParams * MySQL_HostGroups_Manager::get_Server_SSL_Params(char *hostname, int port, char *username) { | ||
string MapKey = string(hostname) + string(rand_del) + to_string(port) + string(rand_del) + string(username); | ||
std::lock_guard<std::mutex> lock(Servers_SSL_Params_map_mutex); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason to pass the vector by value, also, because it's never modified, could be easily converted into
const vector<tuple<string, int, int>>&
.