예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
            }
        }
예제 #4
0
        /// <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;
                }
            }
        }
예제 #5
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();
        }
예제 #6
0
 public abstract Task <object> Execute(BalancerData balancerData, HttpContext context, RawHandler handler);
예제 #7
0
 /// <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]);
 }