consul-resolver
Version:
A load balancer for Consul services with Redis-based metrics
67 lines (66 loc) • 3.1 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.combineHealthAndDNSWeights = exports.rankServices = exports.normalizeScore = exports.calculateDistributionScore = exports.calculateResourceScore = exports.calculateHealthScore = void 0;
const types_1 = require("../types");
function calculateHealthScore(service) {
const checks = service.Checks;
const totalChecks = checks.length;
if (totalChecks === 0)
return 0;
const passingChecks = checks.filter((check) => check.Status === "passing").length;
return passingChecks / totalChecks;
}
exports.calculateHealthScore = calculateHealthScore;
function calculateResourceScore(metrics) {
const cpuScore = normalizeScore(metrics.cpuUsage, 100, true);
const memoryScore = normalizeScore(metrics.memoryUsage, 100, true);
return (cpuScore + memoryScore) / 2;
}
exports.calculateResourceScore = calculateResourceScore;
function calculateDistributionScore(lastSelectedTime) {
if (!lastSelectedTime)
return 1;
const timeSinceLastSelection = Date.now() - lastSelectedTime;
return Math.min(timeSinceLastSelection / (5 * 60 * 1000), 1);
}
exports.calculateDistributionScore = calculateDistributionScore;
function normalizeScore(value, max, inverse = false) {
const normalized = Math.max(0, Math.min(1, value / max));
return inverse ? 1 - normalized : normalized;
}
exports.normalizeScore = normalizeScore;
function rankServices(services, metrics, weights = types_1.DEFAULT_WEIGHTS) {
return services
.map((service) => {
const serviceId = service.Service.ID;
const serviceMetrics = metrics.get(serviceId);
if (!serviceMetrics) {
throw new Error(`No metrics found for service ${serviceId}`);
}
const healthScore = calculateHealthScore(service);
const responseTimeScore = normalizeScore(serviceMetrics.responseTime, 500, true);
const errorRateScore = normalizeScore(serviceMetrics.errorRate, 100, true);
const resourceScore = calculateResourceScore(serviceMetrics);
const connectionScore = normalizeScore(serviceMetrics.activeConnections, 1000, true);
const distributionScore = calculateDistributionScore(serviceMetrics.lastSelectedTime);
const totalScore = healthScore * weights.health +
responseTimeScore * weights.responseTime +
errorRateScore * weights.errorRate +
resourceScore * weights.resources +
connectionScore * weights.connections +
distributionScore * weights.distribution;
return {
score: totalScore,
id: serviceId,
service,
};
})
.sort((a, b) => b.score - a.score);
}
exports.rankServices = rankServices;
function combineHealthAndDNSWeights(service, dnsWeight, maxDNSWeight) {
const healthScore = calculateHealthScore(service);
const normalizedDNSWeight = dnsWeight / maxDNSWeight;
return (healthScore * 0.7) + (normalizedDNSWeight * 0.3);
}
exports.combineHealthAndDNSWeights = combineHealthAndDNSWeights;