Пример #1
0
 protected Pool(Configuration.Config config)
 {
     NrOfInstances     = config.GetInt("nr-of-instances");
     Resizer           = DefaultResizer.FromConfig(config);
     UsePoolDispatcher = config.HasPath("pool-dispatcher");
     // ReSharper restore DoNotCallOverridableMethodsInConstructor
 }
Пример #2
0
 protected Pool(Config config) : base(Dispatchers.DefaultDispatcherId)
 {
     _nrOfInstances     = config.GetInt("nr-of-instances");
     _resizer           = DefaultResizer.FromConfig(config);
     _usePoolDispatcher = config.HasPath("pool-dispatcher");
     // ReSharper restore DoNotCallOverridableMethodsInConstructor
 }
Пример #3
0
 /// <summary>
 /// Creates an instance of the TailChoppingPool.
 /// </summary>
 /// <param name="config">The configuration to use with this instance.</param>
 public TailChoppingPool(Config config)
 {
     NrOfInstances     = config.GetInt("nr-of-instances");
     within            = config.GetMillisDuration("within");
     interval          = config.GetMillisDuration("tail-chopping-router.interval");
     Resizer           = DefaultResizer.FromConfig(config);
     UsePoolDispatcher = config.HasPath("pool-dispatcher");
 }
Пример #4
0
        public void DefaultResizer_must_use_settings_to_evaluate_rampup()
        {
            // ReSharper disable once RedundantArgumentDefaultValue (exposing the values we're testing makes this test understandable.)
            var resizer = new DefaultResizer(2, 10, rampupRate: 0.2d);

            resizer.Rampup(9, 10).ShouldBe(0);
            resizer.Rampup(5, 5).ShouldBe(1);
            resizer.Rampup(6, 6).ShouldBe(2);
        }
Пример #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TailChoppingPool"/> class.
 ///
 /// <note>
 /// 'nr-of-instances', 'within', and 'tail-chopping-router.interval'
 /// must be defined in the provided configuration.
 /// </note>
 /// </summary>
 /// <param name="config">The configuration used to configure the pool.</param>
 public TailChoppingPool(Config config)
     : this(config.GetInt("nr-of-instances"),
            DefaultResizer.FromConfig(config),
            null,
            null, //TODO: what are our defaults? null?
            config.GetTimeSpan("within"),
            config.GetTimeSpan("tail-chopping-router.interval"),
            config.HasPath("pool-dispatcher")
            )
 {
 }
Пример #6
0
        public static Resizer FromConfig(Config parentConfig)
        {
            var defaultResizerConfig = parentConfig.GetConfig("resizer");

            if (defaultResizerConfig != null && defaultResizerConfig.GetBoolean("enabled"))
            {
                return(DefaultResizer.Apply(defaultResizerConfig));
            }
            else
            {
                return(null);
            }
        }
Пример #7
0
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="parentConfig">TBD</param>
        /// <returns>TBD</returns>
        public static Resizer FromConfig(Config parentConfig)
        {
            var defaultResizerConfig = parentConfig.GetConfig("resizer");

            if (!defaultResizerConfig.IsNullOrEmpty() && defaultResizerConfig.GetBoolean("enabled", false))
            {
                return(DefaultResizer.Apply(defaultResizerConfig));
            }
            else
            {
                return(null);
            }
        }
Пример #8
0
        public void DefaultResizer_must_use_settings_to_evaluate_backoff()
        {
            // ReSharper disable RedundantArgumentDefaultValue (exposing the values we're testing makes this test understandable.)
            var resizer = new DefaultResizer(2, 10, backoffThreshold: 0.3d, backoffRate: 0.1d);
            // ReSharper restore RedundantArgumentDefaultValue

            resizer.Backoff(10, 10).ShouldBe(0);
            resizer.Backoff(4, 10).ShouldBe(0);
            resizer.Backoff(3, 10).ShouldBe(0);
            resizer.Backoff(2, 10).ShouldBe(-1);
            resizer.Backoff(0, 10).ShouldBe(-1);
            resizer.Backoff(1, 9).ShouldBe(-1);
            resizer.Backoff(0, 9).ShouldBe(-1);
        }
Пример #9
0
        public void DefaultResizer_must_use_settings_to_evaluate_capacity()
        {
            var resizer = new DefaultResizer(2, 3);
            var c1 = resizer.Capacity(new Routee[] { });
            c1.ShouldBe(2);

            var current = new Routee[]
            {
                new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()),
                new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>())
            };
            var c2 = resizer.Capacity(current);
            c2.ShouldBe(0);
        }
Пример #10
0
        public void DefaultResizer_must_use_settings_to_evaluate_capacity()
        {
            var resizer = new DefaultResizer(lower: 2, upper: 3);
            var c1 = resizer.Capacity(Enumerable.Empty<Routee>());
            c1.Should().Be(2);

            var current = new Routee[]
            {
                new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>()),
                new ActorRefRoutee(Sys.ActorOf<ResizerTestActor>())
            };

            var c2 = resizer.Capacity(current);
            c2.Should().Be(0);
        }
Пример #11
0
        public void DefaultResizer_must_use_settings_to_evaluate_backoff()
        {
            var resizer = new DefaultResizer(lower: 2, upper: 10, backoffThreshold: 0.3d, backoffRate: 0.1d);

            resizer.Backoff(pressure: 10, capacity: 10).Should().Be(0);
            resizer.Backoff(pressure: 4, capacity: 10).Should().Be(0);
            resizer.Backoff(pressure: 3, capacity: 10).Should().Be(0);
            resizer.Backoff(pressure: 2, capacity: 10).Should().Be(-1);
            resizer.Backoff(pressure: 0, capacity: 10).Should().Be(-1);
            resizer.Backoff(pressure: 1, capacity: 9).Should().Be(-1);
            resizer.Backoff(pressure: 0, capacity: 9).Should().Be(-1);
        }
Пример #12
0
        public void DefaultResizer_must_be_possible_to_define_programmatically()
        {
            var latch = new TestLatch(3);
            var resizer = new DefaultResizer(lower: 2, upper: 3);

            var router = Sys.ActorOf(new RoundRobinPool(0, resizer).Props(Props.Create<ResizerTestActor>()));

            router.Tell(latch);
            router.Tell(latch);
            router.Tell(latch);

            latch.Ready(RemainingOrDefault);

            // MessagesPerResize is 10 so there is no risk of additional resize
            RouteeSize(router).Should().Be(2);
        }
Пример #13
0
        public void DefaultResizer_must_be_possible_to_define_programmatically()
        {
            var latch = new TestLatch(Sys, 3);
            var resizer = new DefaultResizer(2, 3);
            var router = Sys.ActorOf(Props.Create<ResizerTestActor>().WithRouter(new RoundRobinPool(0, resizer)));

            router.Tell(latch);
            router.Tell(latch);
            router.Tell(latch);

            latch.Ready(TestKitSettings.DefaultTimeout);

            //messagesPerResize is 10 so there is no risk of additional resize
            (RouteeSize(router)).ShouldBe(2);
        }
Пример #14
0
        public void DefaultResizer_must_grow_as_needed_under_pressure()
        {
            var resizer = new DefaultResizer(
                lower: 3,
                upper: 5,
                rampupRate: 0.1,
                backoffRate: 0.0,
                pressureThreshold: 1,
                messagesPerResize: 1,
                backoffThreshold: 0.0);

            var router = Sys.ActorOf(new RoundRobinPool(0, resizer).Props(Props.Create<PressureActor>()));

            // first message should create the minimum number of routees
            router.Tell("echo");
            ExpectMsg("reply");

            RouteeSize(router).Should().Be(resizer.LowerBound);

            Action<int, TimeSpan> loop = (loops, d) =>
            {
                for (var i = 0; i < loops; i++)
                {
                    router.Tell(d);

                    //sending too quickly will result in skipped resize due to many ResizeInProgress conflicts
                    Thread.Sleep(Dilated(20.Milliseconds()));
                }

                double max = d.TotalMilliseconds * loops / resizer.LowerBound + Dilated(2.Seconds()).TotalMilliseconds;
                Within(TimeSpan.FromMilliseconds(max), () =>
                {
                    for (var i = 0; i < loops; i++)
                    {
                        ExpectMsg("done");
                    }
                });
            };

            // 2 more should go through without triggering more
            loop(2, 200.Milliseconds());
            RouteeSize(router).Should().Be(resizer.LowerBound);

            // a whole bunch should max it out
            loop(20, 500.Milliseconds());
            RouteeSize(router).Should().Be(resizer.UpperBound);
        }
Пример #15
0
        public void DefaultResizer_must_grow_as_needed_under_pressure()
        {
            var resizer = new DefaultResizer(3, 5, pressureThreshold: 1, rampupRate: 0.1d, backoffRate: 0.0d,
                messagesPerResize: 1, backoffThreshold: 0.0d);

            var router = Sys.ActorOf(Props.Create<PressureActor>().WithRouter(new RoundRobinPool(0, resizer)));

            //first message should create the minimum number of routees
            router.Tell("echo", TestActor);
            ExpectMsg("reply", TimeSpan.FromSeconds(1));

            (RouteeSize(router)).ShouldBe(resizer.LowerBound);

            Action<int, TimeSpan> loop = (loops, span) =>
            {
                for (var i = 0; i < loops; i++)
                {
                    router.Tell(span, TestActor);
                    //sending too quickly will result in skipped resize due to many resizeInProgress conflicts
                    Thread.Sleep(TimeSpan.FromMilliseconds(20));
                }
                Within(
                    TimeSpan.FromMilliseconds(span.TotalMilliseconds * loops / resizer.LowerBound) + TimeSpan.FromSeconds(2.5),
                    () =>
                    {
                        for (var i = 0; i < loops; i++) ExpectMsg("done");
                        return true;
                    });
            };

            

            // 2 more should go through without triggering more
            loop(2, TimeSpan.FromMilliseconds(200));
            RouteeSize(router).ShouldBe(resizer.LowerBound);


            // a whole bunch should max it out
            loop(20, TimeSpan.FromMilliseconds(500));
            RouteeSize(router).ShouldBe(resizer.UpperBound);

        }
Пример #16
0
        public void DefaultResizer_must_backoff_within_10_seconds()
        {
            var resizer = new DefaultResizer(2, 5, pressureThreshold: 1, rampupRate: 1.0d, backoffRate: 1.0d,
               messagesPerResize: 2, backoffThreshold: 0.4d);

            var router = Sys.ActorOf(Props.Create<BackoffActor>().WithRouter(new RoundRobinPool(0, resizer)));

            // put some pressure on the router
            for (var i = 0; i < 15; i++)
            {
                router.Tell(150);
                Thread.Sleep(20);
            }

            var z = RouteeSize(router);
            Assert.True(z > 2);
            Thread.Sleep(300);

            // let it cool down
            AwaitCondition(() =>
            {
                router.Tell(0); //trigger resize
                Thread.Sleep(20);
                return RouteeSize(router) < z;
            }, TimeSpan.FromMilliseconds(500));
        }
Пример #17
0
        public void DefaultResizer_must_use_settings_to_evaluate_rampup()
        {
            var resizer = new DefaultResizer(lower: 2, upper: 10, rampupRate: 0.2);

            resizer.Rampup(pressure: 9, capacity: 10).Should().Be(0);
            resizer.Rampup(pressure: 5, capacity: 5).Should().Be(1);
            resizer.Rampup(pressure: 6, capacity: 6).Should().Be(2);
        }
Пример #18
0
        public void DefaultResizer_must_backoff()
        {
            Within(TimeSpan.FromSeconds(10), () =>
            {   
               var resizer = new DefaultResizer(2, 5, pressureThreshold: 1, rampupRate: 1.0d, backoffRate: 1.0d,
               messagesPerResize: 2, backoffThreshold: 0.4d);

                var router = Sys.ActorOf(Props.Create<BackoffActor>().WithRouter(new RoundRobinPool(0, resizer)));

                // put some pressure on the router
                for (var i = 0; i < 200; i++)
                {
                    router.Tell(150);
                    if (RouteeSize(router) > 2) 
                        break;

                    Thread.Sleep(20);
                }

                var z = RouteeSize(router);
                Assert.True(z > 2);
                Thread.Sleep(300);

                // let it cool down
                AwaitAssert(() =>
                {
                    router.Tell(0); //trigger resize
                    Thread.Sleep(20);
                    RouteeSize(router).Should().BeLessThan(z);
                }, null, TimeSpan.FromSeconds(1));
            });
        }
Пример #19
0
        public void DefaultResizer_must_grow_as_needed_under_pressure()
        {
            var resizer = new DefaultResizer(3, 5, pressureThreshold: 1, rampupRate: 0.1d, backoffRate: 0.0d,
                messagesPerResize: 1, backoffThreshold: 0.0d);

            var router = Sys.ActorOf(Props.Create<PressureActor>().WithRouter(new RoundRobinPool(0, resizer)));

            //first message should create the minimum number of routees
            router.Tell("echo", TestActor);
            ExpectMsg("reply");

            (RouteeSize(router)).ShouldBe(resizer.LowerBound);

            Action<int, TimeSpan, int?> loopTillAppropriateSize = (loops, span, expectedBound) =>
            {
                for (var i = 0; i < loops; i++)
                {
                    router.Tell(span, TestActor);
                    if (expectedBound.HasValue && RouteeSize(router) >= expectedBound.Value)
                    {
                        return;
                    }

                    //sending too quickly will result in skipped resize due to many resizeInProgress conflicts
                    Thread.Sleep(TimeSpan.FromMilliseconds(20));
                }
            };

            // 2 more should go through without triggering more
            loopTillAppropriateSize(2, TimeSpan.FromMilliseconds(200), null);
            RouteeSize(router).ShouldBe(resizer.LowerBound);

            // a whole bunch should max it out
            loopTillAppropriateSize(200, TimeSpan.FromMilliseconds(500), resizer.UpperBound);
            RouteeSize(router).ShouldBe(resizer.UpperBound);
        }
Пример #20
0
        public void DefaultResizer_must_backoff()
        {
            Within(10.Seconds(), () =>
            {
                var resizer = new DefaultResizer(
                    lower: 2,
                    upper: 5,
                    rampupRate: 1.0d,
                    backoffRate: 1.0d,
                    backoffThreshold: 0.40d,
                    pressureThreshold: 1,
                    messagesPerResize: 2);

                var router = Sys.ActorOf(new RoundRobinPool(nrOfInstances: 0, resizer : resizer)
                    .Props(Props.Create(() => new BackoffActor(Dilated))));

                // put some pressure on the router
                for (var i = 0; i < 15; i++)
                {
                    router.Tell(150);

                    Thread.Sleep(Dilated(20.Milliseconds()));
                }

                var z = RouteeSize(router);
                z.Should().BeGreaterThan(2);

                Thread.Sleep(Dilated(300.Milliseconds()));

                // let it cool down
                AwaitCondition(() =>
                {
                    router.Tell(0); //trigger resize
                    Thread.Sleep(Dilated(20.Milliseconds()));
                    return RouteeSize(router) < z;
                }, Dilated(500.Milliseconds()));
            });
        }
Пример #21
0
 protected Pool(Configuration.Config config)
 {
     NrOfInstances     = config.GetInt("nr-of-instances");
     Resizer           = DefaultResizer.FromConfig(config);
     UsePoolDispatcher = config.HasPath("pool-dispatcher");
 }