Ejemplo n.º 1
0
        protected virtual string GetNextHostAddressInBalancingSet()
        {
            /*
             * Use the the address list as circular buffer with a pointer maintenaned
             * as a state. if the list is empty (or was emptied by mistake) return an exception.
             *
             * we cheated a bit here routing is
             * A-B-C
             * A-B-C
             * until we hit int.MaxValue then
             * C-B-A
             * C-B-A
             * until we hit 0 then
             * A-B-C
             * A-B-C
             *
             * Overall it is R/R
             */

            var    sStateKey      = string.Format(State_Key_LoadBalancingSet, MatcherTreeId);
            var    loadbalanceIdx = (LoadBalanceIdx)Resolver.State.StateEntries.GetOrAdd(sStateKey, (dictKey) => { return(new LoadBalanceIdx()); });
            string nextAddress    = null;

            while (true)
            {
                try
                {
                    var newIdx = Math.Abs(Interlocked.Increment(ref loadbalanceIdx.Idx));

                    // if the list was emptied by mistake, we will go to DivideByZeroException
                    nextAddress = TargetHostAddressList[newIdx % TargetHostAddressList.Count];

                    // so if address was removed after we picked it up, we just try agian
                    if (TargetHostAddressList.Contains(nextAddress))
                    {
                        break;
                    }
                }
                catch (DivideByZeroException)
                {
                    //somebody cleared the address list while we are trying to pick an address
                    throw new InvalidOperationException("Load balancing set is empty");
                }
                catch (ArgumentOutOfRangeException)
                {
                    // this will happen if the list got replaced with a shorter list
                    // after we picked a position > sizeof(new list). ingore and try again.
                }
                // anyother exception should be vented up the stack.
            }


            return(nextAddress);
        }
Ejemplo n.º 2
0
        public override async Task <bool> MatchAsync(RoutingContextBase routingContext,
                                                     string sAddress,
                                                     IDictionary <string, object> Context,
                                                     Stream Body)
        {
            // validate, null list is bad
            if (null == this.TargetHostAddressList)
            {
                throw new ArgumentNullException("TargetHostAddresses");
            }


            // a list that has a null or empty is also bad
            var nullAddresses = TargetHostAddressList.Where(s => string.IsNullOrEmpty(s));

            if (0 != nullAddresses.Count())
            {
                throw new ArgumentNullException("TargetHostAddresses contains null or empty host addresses");
            }



            if (false == await base.MatchAsync(routingContext, sAddress, Context, Body))
            {
                return(false);
            }

            if (Clear)
            {
                routingContext.TargetHostAddressList.Clear();
            }


            routingContext.TargetHostAddressList.AddRange(TargetHostAddressList);
            routingContext.RouteExecuteType = this.RoutingType;


            return(true);
        }
Ejemplo n.º 3
0
        public override async Task <RoutingResultBase> ExecuteAsync(ContextExecuteModeBase executeMode)
        {
            // validate that the passed execution mode is supported by this context.
            if (!IsAllowedExecutionMode(executeMode))
            {
                throw new NotSupportedExecuteModeException(string.Format("Context of type {0} can not support execute mode of type {1}",
                                                                         this.GetType().ToString(),
                                                                         executeMode.GetType().ToString()));
            }



            var result = new HttpRoutingResult();

            result.ExecutionContext = this;



            switch (RouteExecuteType)
            {
            case ContextRoutingType.Single:
            {
                var host     = TargetHostAddressList[0];
                var hrm      = getRequestMessage(host);
                var client   = GetHttpClientForHost(host);
                var response = await client.SendAsync(hrm);

                result.SetResult(response);

                break;
            }

            case ContextRoutingType.FastestRoute:
            {
                var tasks = new List <Task <HttpResponseMessage> >(TargetHostAddressList.Count());
                foreach (var host in TargetHostAddressList)
                {
                    var client = GetHttpClientForHost(host);
                    var hrm    = getRequestMessage(host);

                    tasks.Add(client.SendAsync(hrm));
                }
                // TPL hoorah!
                var completedTask = await Task.WhenAny <HttpResponseMessage>(tasks);

                result.SetResult(await completedTask);

                break;
            }

            case ContextRoutingType.ScatterGather:
            {
                var tasks = new List <Task <HttpResponseMessage> >(TargetHostAddressList.Count());
                foreach (var host in TargetHostAddressList)
                {
                    var client = GetHttpClientForHost(host);
                    var hrm    = getRequestMessage(host);
                    tasks.Add(client.SendAsync(hrm));
                }

                await Task.WhenAll(tasks);

                var responses = new List <HttpResponseMessage>(TargetHostAddressList.Count());
                foreach (var completedtask in tasks)
                {
                    responses.Add(completedtask.Result);
                }


                result.SetResult(responses);

                break;
            }

            case ContextRoutingType.RoundRobin:
            {
                var host     = GetNextHostAddressInBalancingSet();
                var hrm      = getRequestMessage(host);
                var client   = GetHttpClientForHost(host);
                var response = await client.SendAsync(hrm);

                result.SetResult(response);
                break;
            }

            default:
            {
                throw new InvalidOperationException(string.Format("invalid routing type for http router", RouteExecuteType.ToString()));
            }
            }



            return(result);
        }