public async override Task <object> Execute(BalancerData balancerData, HttpContext context, RawHandler handler) { var vhost = context.Items["bal-vhost"] as BalancerOption; var key = balancerData.Scores.OrderByDescending(x => x.Value).FirstOrDefault().Key; var node = vhost.Nodes[key]; await handler.HandleRequest(context, node); return(node); }
public async override Task <object> Execute(BalancerData balancerData, HttpContext context, RawHandler handler) { var vhost = context.Items["bal-vhost"] as BalancerOption; balancerData.LastServed = (balancerData.LastServed + 1) % vhost.Nodes.Length; var node = vhost.Nodes[balancerData.LastServed]; await handler.HandleRequest(context, node); return(node); }
public override async Task InvokeAsync(HttpContext context) { logger.LogDebug("Invoke BalancerMiddleware start"); var host = context.Request.Host.Value; var scheme = context.Request.Scheme; var port = context.Request.Host.Port; var path = context.Request.Path; var vhosts = pluginConfig?.Balancer?.Where(x => x.Host.Equals(host, StringComparison.InvariantCultureIgnoreCase) && x.Scheme.Equals(scheme, StringComparison.InvariantCultureIgnoreCase) && new Regex(x.Path).Match(path).Success&& x.Port == port && x.Enable).ToList(); // TODO: get regex that not contains other regex var vhost = vhosts?.OrderByDescending(x => x.Path?.Length).FirstOrDefault(); if (vhost != null) { vhost.Nodes = vhost.Nodes.Where(x => x.Enable).ToArray(); } context.Items["bal-host"] = host; context.Items["bal-vhost"] = vhost; var policy = dispatcher.GetActiveBalancerPolicy(context); if (policy != null) { BalancerData balancerData = null; if (!data.ContainsKey(host)) { balancerData = data[host] = new BalancerData(); for (int i = 0; i < vhost.Nodes.Length; i++) { balancerData.Scores[i] = 0; } } else { balancerData = data[host]; } context.Request.Headers["X-Forwarded-For"] = context.Connection.RemoteIpAddress.ToString(); context.Request.Headers["X-Forwarded-Proto"] = context.Request.Protocol.ToString(); int portDest = context.Request.Host.Port ?? (context.Request.IsHttps ? 443 : 80); context.Request.Headers["X-Forwarded-Port"] = portDest.ToString(); var handlerType = context.WebSockets.IsWebSocketRequest ? HandlerProtocolType.Socket : HandlerProtocolType.Http; context.Items["bal-destination"] = await policy.Execute(balancerData, context, handlers.First(x => x.HandlerRequestType == handlerType)); } else { await next(context); } }
/// <summary> /// Request count implementation /// </summary> /// <param name="balancerData"></param> /// <param name="options"></param> /// <returns></returns> private Node RequestCount(BalancerData balancerData, BalancerOptions options) { var key = balancerData.Scores.OrderByDescending(x => x.Value).FirstOrDefault().Key; return(options.Nodes[key]); if (balancerData.Scores[key] + 1 < long.MaxValue) { balancerData.Scores[key]++; } else { //If i'm going outside long range I need a reset. //i'm the lower value, so if I'm not able to increments all other have my same value (if not, they had ben triggered this previously) for (int i = 0; i < balancerData.Scores.Count; i++) { balancerData.Scores[i] = 0; } } }
public async override Task InvokeImpl(HttpContext context, string host, VHostOptions vhost, IConfigurationSection settings) { BalancerOptions options = new BalancerOptions(); settings.Bind("Settings:Balancer", options); BalancerData balancerData = null; if (!data.ContainsKey(host)) { balancerData = data[host] = new BalancerData(); for (int i = 0; i < options.Nodes.Length; i++) { balancerData.Scores[i] = 0; } } else { balancerData = data[host]; } //Different logic basing on algoritm //TODO: make it generic using interface\implementation for algoritm if (options.Policy == "RoundRobin") { context.Items["bal-destination"] = RoundRobin(balancerData, options); } else if (options.Policy == "RequestCount") { context.Items["bal-destination"] = RequestCount(balancerData, options); } //Alter request context.Request.Headers["X-Forwarded-For"] = context.Connection.RemoteIpAddress.ToString(); context.Request.Headers["X-Forwarded-Proto"] = context.Request.Protocol.ToString(); int port = context.Request.Host.Port ?? (context.Request.IsHttps ? 443 : 80); context.Request.Headers["X-Forwarded-Port"] = port.ToString(); }
public abstract Task <object> Execute(BalancerData balancerData, HttpContext context, RawHandler handler);
/// <summary> /// Roud robin implementation /// </summary> /// <param name="balancerData"></param> /// <param name="options"></param> /// <returns></returns> private object RoundRobin(BalancerData balancerData, BalancerOptions options) { balancerData.LastServed = (balancerData.LastServed + 1) % options.Nodes.Length; return(options.Nodes[balancerData.LastServed]); }