MXS-2219 Update datastructures instead of recreating them
The node infos of the Clustrix servers are now kept around and and updated based upon changing conditions instead of regularly being re-created. Further, the server is now looked up by name only right after having been created (and that only due to runtime_create_server() currently being used). The state of the dynamically created server is now updated directly as a result of the health-check ping, while the state of the bootstrap servers is updated during the tick()-call according to the monitor "protocol".
This commit is contained in:
@ -13,6 +13,7 @@
|
||||
|
||||
#include "clustrixmonitor.hh"
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include "../../../core/internal/config_runtime.hh"
|
||||
|
||||
namespace http = mxb::http;
|
||||
@ -135,11 +136,14 @@ void ClustrixMonitor::fetch_cluster_nodes_from(MXS_MONITORED_SERVER& ms)
|
||||
{
|
||||
mxb_assert(mysql_field_count(ms.con) == 4);
|
||||
|
||||
vector<ClustrixNodeInfo> node_infos;
|
||||
vector<string> health_urls;
|
||||
|
||||
MYSQL_ROW row;
|
||||
|
||||
set<int> nids;
|
||||
for_each(m_node_infos.begin(), m_node_infos.end(),
|
||||
[&nids](const pair<int, ClustrixNodeInfo>& element) {
|
||||
nids.insert(element.first);
|
||||
});
|
||||
|
||||
while ((row = mysql_fetch_row(pResult)) != nullptr)
|
||||
{
|
||||
if (row[0] && row[1])
|
||||
@ -150,37 +154,70 @@ void ClustrixMonitor::fetch_cluster_nodes_from(MXS_MONITORED_SERVER& ms)
|
||||
int health_port = row[3] ? atoi(row[3]) : DEFAULT_HEALTH_PORT;
|
||||
int health_check_threshold = m_config.health_check_threshold();
|
||||
|
||||
string name = "Clustrix-Server-" + std::to_string(id);
|
||||
string name = "@Clustrix-Server-" + std::to_string(id);
|
||||
|
||||
if (SERVER::find_by_unique_name(name) ||
|
||||
runtime_create_server(name.c_str(),
|
||||
ip.c_str(),
|
||||
std::to_string(mysql_port).c_str(),
|
||||
"mariadbbackend",
|
||||
"mysqlbackendauth",
|
||||
false))
|
||||
{
|
||||
node_infos.emplace_back(id, ip, mysql_port, health_port, health_check_threshold);
|
||||
auto it = m_node_infos.find(id);
|
||||
|
||||
string health_url = "http://" + ip + ":" + std::to_string(health_port);
|
||||
health_urls.push_back(health_url);
|
||||
if (it == m_node_infos.end())
|
||||
{
|
||||
mxb_assert(!SERVER::find_by_unique_name(name));
|
||||
|
||||
if (runtime_create_server(name.c_str(),
|
||||
ip.c_str(),
|
||||
std::to_string(mysql_port).c_str(),
|
||||
"mariadbbackend",
|
||||
"mysqlbackendauth",
|
||||
false))
|
||||
{
|
||||
SERVER* pServer = SERVER::find_by_unique_name(name);
|
||||
mxb_assert(pServer);
|
||||
|
||||
ClustrixNodeInfo info(id, ip, mysql_port, health_port, health_check_threshold, pServer);
|
||||
|
||||
m_node_infos.insert(make_pair(id, info));
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not create server %s at %s:%d.",
|
||||
name.c_str(), ip.c_str(), mysql_port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Could not create server %s at %s:%d.",
|
||||
name.c_str(), ip.c_str(), mysql_port);
|
||||
mxb_assert(SERVER::find_by_unique_name(name));
|
||||
|
||||
auto it = nids.find(id);
|
||||
mxb_assert(it != nids.end());
|
||||
nids.erase(it);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_WARNING("Either nodeid and/or iface_ip is missing, "
|
||||
"ignoring node.");
|
||||
MXS_WARNING("Either nodeid and/or iface_ip is missing, ignoring node.");
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(pResult);
|
||||
|
||||
m_node_infos.swap(node_infos);
|
||||
for_each(nids.begin(), nids.end(),
|
||||
[this](int nid) {
|
||||
auto it = m_node_infos.find(nid);
|
||||
mxb_assert(it != m_node_infos.end());
|
||||
|
||||
ClustrixNodeInfo& info = it->second;
|
||||
info.deactivate_server();
|
||||
m_node_infos.erase(it);
|
||||
});
|
||||
|
||||
vector<string> health_urls;
|
||||
for_each(m_node_infos.begin(), m_node_infos.end(),
|
||||
[&health_urls](const pair<int, ClustrixNodeInfo>& element) {
|
||||
const ClustrixNodeInfo& info = element.second;
|
||||
string url = "http://" + info.ip() + ":" + std::to_string(info.health_port());
|
||||
|
||||
health_urls.push_back(url);
|
||||
});
|
||||
|
||||
m_health_urls.swap(health_urls);
|
||||
|
||||
m_last_cluster_check = now();
|
||||
@ -233,13 +270,16 @@ void ClustrixMonitor::update_server_statuses()
|
||||
monitor_stash_current_status(&ms);
|
||||
|
||||
auto it = find_if(m_node_infos.begin(), m_node_infos.end(),
|
||||
[&ms](const ClustrixNodeInfo& info) -> bool {
|
||||
[&ms](const std::pair<int,ClustrixNodeInfo>& element) -> bool {
|
||||
const ClustrixNodeInfo& info = element.second;
|
||||
return ms.server->address == info.ip();
|
||||
});
|
||||
|
||||
if (it != m_node_infos.end())
|
||||
{
|
||||
if (it->is_running())
|
||||
const ClustrixNodeInfo& info = it->second;
|
||||
|
||||
if (info.is_running())
|
||||
{
|
||||
monitor_set_pending_status(&ms, SERVER_RUNNING);
|
||||
}
|
||||
@ -310,21 +350,23 @@ bool ClustrixMonitor::check_http(Call::action_t action)
|
||||
{
|
||||
const vector<http::Result>& results = m_http.results();
|
||||
|
||||
for (size_t i = 0; i < results.size(); ++i)
|
||||
{
|
||||
const auto& result = results[i];
|
||||
auto it = m_node_infos.begin();
|
||||
|
||||
bool running = false;
|
||||
for_each(results.begin(), results.end(),
|
||||
[&it](const http::Result& result) {
|
||||
bool running = false;
|
||||
|
||||
if (result.code == 200)
|
||||
{
|
||||
running = true;
|
||||
}
|
||||
if (result.code == 200)
|
||||
{
|
||||
running = true;
|
||||
}
|
||||
|
||||
auto& node_info = m_node_infos[i];
|
||||
auto& node_info = it->second;
|
||||
|
||||
node_info.set_running(running);
|
||||
}
|
||||
node_info.set_running(running);
|
||||
|
||||
++it;
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "clustrixmon.hh"
|
||||
#include <map>
|
||||
#include <maxscale/monitor.hh>
|
||||
#include <maxbase/http.hh>
|
||||
#include "clustrixnodeinfo.hh"
|
||||
@ -85,12 +86,12 @@ private:
|
||||
}
|
||||
|
||||
private:
|
||||
Config m_config;
|
||||
std::vector<std::string> m_config_servers;
|
||||
std::vector<ClustrixNodeInfo> m_node_infos;
|
||||
std::vector<std::string> m_health_urls;
|
||||
mxb::http::Async m_http;
|
||||
uint32_t m_delayed_http_check_id { 0 };
|
||||
long m_last_cluster_check { 0 };
|
||||
MXS_MONITORED_SERVER* m_pMonitored_server { nullptr };
|
||||
Config m_config;
|
||||
std::vector<std::string> m_config_servers;
|
||||
std::map<int, ClustrixNodeInfo> m_node_infos;
|
||||
std::vector<std::string> m_health_urls;
|
||||
mxb::http::Async m_http;
|
||||
uint32_t m_delayed_http_check_id { 0 };
|
||||
long m_last_cluster_check { 0 };
|
||||
MXS_MONITORED_SERVER* m_pMonitored_server { nullptr };
|
||||
};
|
||||
|
@ -24,13 +24,15 @@ public:
|
||||
const std::string& ip,
|
||||
int mysql_port,
|
||||
int health_port,
|
||||
int health_check_threshold)
|
||||
int health_check_threshold,
|
||||
SERVER* pServer)
|
||||
: m_id(id)
|
||||
, m_ip(ip)
|
||||
, m_mysql_port(mysql_port)
|
||||
, m_health_port(health_port)
|
||||
, m_health_check_threshold(health_check_threshold)
|
||||
, m_nRunning(m_health_check_threshold)
|
||||
, m_pServer(pServer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -64,16 +66,28 @@ public:
|
||||
if (running)
|
||||
{
|
||||
m_nRunning = m_health_check_threshold;
|
||||
|
||||
m_pServer->set_status(SERVER_RUNNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nRunning > 0)
|
||||
{
|
||||
--m_nRunning;
|
||||
|
||||
if (m_nRunning == 0)
|
||||
{
|
||||
m_pServer->clear_status(SERVER_RUNNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deactivate_server()
|
||||
{
|
||||
m_pServer->is_active = false;
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
@ -93,6 +107,7 @@ private:
|
||||
int m_health_port;
|
||||
int m_health_check_threshold;
|
||||
int m_nRunning;
|
||||
SERVER* m_pServer;
|
||||
};
|
||||
|
||||
inline std::ostream& operator << (std::ostream& out, const ClustrixNodeInfo& x)
|
||||
|
Reference in New Issue
Block a user