Load balancer improvements / source selection
This commit is contained in:
parent
055c87a2b3
commit
2c5b5c0460
1 changed files with 64 additions and 12 deletions
|
@ -19,9 +19,10 @@ unsigned int weight_bw = 1000;
|
|||
unsigned int weight_bonus = 50;
|
||||
|
||||
struct streamDetails{
|
||||
unsigned int total;
|
||||
unsigned int bandwidth;
|
||||
unsigned long long prevTotal;
|
||||
uint32_t total;
|
||||
uint32_t inputs;
|
||||
uint32_t bandwidth;
|
||||
uint32_t prevTotal;
|
||||
};
|
||||
|
||||
class hostDetails{
|
||||
|
@ -124,6 +125,29 @@ class hostDetails{
|
|||
MEDIUM_MSG("%s: CPU %u, RAM %u, Stream %u, BW %u (max %llu MB/s) -> %u", host.c_str(), cpu_score, ram_score, streams.count(s)?weight_bonus:0, bw_score, availBandwidth / 1024 / 1024, score);
|
||||
return score;
|
||||
}
|
||||
///Scores this server as a source
|
||||
///0 means not possible, the higher the better.
|
||||
unsigned int source(std::string & s){
|
||||
if (!hostMutex){hostMutex = new tthread::mutex();}
|
||||
tthread::lock_guard<tthread::mutex> guard(*hostMutex);
|
||||
if (!streams.count(s) || !streams[s].inputs){return 0;}
|
||||
if (!ramMax || !availBandwidth){
|
||||
WARN_MSG("Host %s invalid: RAM %llu, BW %llu", host.c_str(), ramMax, availBandwidth);
|
||||
return 1;
|
||||
}
|
||||
if (upSpeed >= availBandwidth || (upSpeed + addBandwidth) >= availBandwidth){
|
||||
INFO_MSG("Host %s over bandwidth: %llu+%llu >= %llu", host.c_str(), upSpeed, addBandwidth, availBandwidth);
|
||||
return 1;
|
||||
}
|
||||
//Calculate score
|
||||
unsigned int cpu_score = (weight_cpu - (cpu*weight_cpu)/1000);
|
||||
unsigned int ram_score = (weight_ram - ((ramCurr * weight_ram) / ramMax));
|
||||
unsigned int bw_score = (weight_bw - (((upSpeed + addBandwidth) * weight_bw) / availBandwidth));
|
||||
unsigned int score = cpu_score + ram_score + bw_score + 1;
|
||||
//Print info on host
|
||||
MEDIUM_MSG("SOURCE %s: CPU %u, RAM %u, Stream %u, BW %u (max %llu MB/s) -> %u", host.c_str(), cpu_score, ram_score, streams.count(s)?weight_bonus:0, bw_score, availBandwidth / 1024 / 1024, score);
|
||||
return score;
|
||||
}
|
||||
void addViewer(std::string & s){
|
||||
if (!hostMutex){hostMutex = new tthread::mutex();}
|
||||
tthread::lock_guard<tthread::mutex> guard(*hostMutex);
|
||||
|
@ -184,6 +208,7 @@ class hostDetails{
|
|||
}
|
||||
struct streamDetails & strm = streams[it.key()];
|
||||
strm.total = (*it)["curr"][0u].asInt();
|
||||
strm.inputs = (*it)["curr"][1u].asInt();
|
||||
unsigned long long currTotal = (*it)["bw"][0u].asInt() + (*it)["bw"][1u].asInt();
|
||||
if (timeDiff && count){
|
||||
strm.bandwidth = ((currTotal - strm.prevTotal) / timeDiff) / count;
|
||||
|
@ -225,6 +250,8 @@ int handleRequest(Socket::Connection & conn){
|
|||
std::string host = H.GetVar("host");
|
||||
std::string stream = H.GetVar("stream");
|
||||
std::string viewers = H.GetVar("viewers");
|
||||
std::string source = H.GetVar("source");
|
||||
std::string fback = H.GetVar("fallback");
|
||||
H.Clean();
|
||||
H.SetHeader("Content-Type", "text/plain");
|
||||
JSON::Value ret;
|
||||
|
@ -236,21 +263,46 @@ int handleRequest(Socket::Connection & conn){
|
|||
H.SendResponse("200", "OK", conn);
|
||||
H.Clean();
|
||||
continue;
|
||||
}else{
|
||||
if (!host.size() && !stream.size()){
|
||||
for (std::map<std::string, hostDetails>::iterator it = hosts.begin(); it != hosts.end(); ++it){
|
||||
it->second.fillState(ret[it->first]);
|
||||
}
|
||||
}else{
|
||||
if (hosts.count(host)){
|
||||
hosts[host].fillState(ret);
|
||||
}
|
||||
if (source.size()){
|
||||
INFO_MSG("Finding source for stream %s", source.c_str());
|
||||
std::string bestHost = "";
|
||||
unsigned int bestScore = 0;
|
||||
for (std::map<std::string, hostDetails>::iterator it = hosts.begin(); it != hosts.end(); ++it){
|
||||
unsigned int score = it->second.source(source);
|
||||
if (score > bestScore){
|
||||
bestHost = "dtsc://"+it->first;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
H.SetBody(ret.toPrettyString());
|
||||
if (bestScore == 0){
|
||||
if (fback.size()){
|
||||
bestHost = fback;
|
||||
}else{
|
||||
bestHost = fallback;
|
||||
}
|
||||
FAIL_MSG("No source for %s found!", source.c_str());
|
||||
}else{
|
||||
INFO_MSG("Winner: %s scores %u", bestHost.c_str(), bestScore);
|
||||
}
|
||||
H.SetBody(bestHost);
|
||||
H.SendResponse("200", "OK", conn);
|
||||
H.Clean();
|
||||
continue;
|
||||
}
|
||||
if (!host.size() && !stream.size()){
|
||||
for (std::map<std::string, hostDetails>::iterator it = hosts.begin(); it != hosts.end(); ++it){
|
||||
it->second.fillState(ret[it->first]);
|
||||
}
|
||||
}else{
|
||||
if (hosts.count(host)){
|
||||
hosts[host].fillState(ret);
|
||||
}
|
||||
}
|
||||
H.SetBody(ret.toPrettyString());
|
||||
H.SendResponse("200", "OK", conn);
|
||||
H.Clean();
|
||||
continue;
|
||||
}
|
||||
std::string stream = H.url.substr(1);
|
||||
if (stream == "favicon.ico"){
|
||||
|
|
Loading…
Add table
Reference in a new issue