/// <inheritdoc/> public override Task Initialize(string strProviderName, IStreamQueueMapper queueMapper, TimeSpan siloMaturityPeriod) { if (queueMapper == null) { throw new ArgumentNullException("queueMapper"); } var options = this.serviceProvider.GetRequiredService <IOptionsSnapshot <LeaseBasedQueueBalancerOptions> >().Get(strProviderName); if (options == null) { throw new KeyNotFoundException($"No lease base queue balancer options was configured for provider {strProviderName}, nor was a default configured."); } this.leaseProvider = this.serviceProvider.GetRequiredService(options.LeaseProviderType) as ILeaseProvider; this.leaseLength = options.LeaseLength; this.allQueues = new ReadOnlyCollection <QueueId>(queueMapper.GetAllQueues().ToList()); this.siloMaturityPeriod = siloMaturityPeriod; NotifyAfterStart().Ignore(); //make lease renew frequency to be every half of lease time, to avoid renew failing due to timing issues, race condition or clock difference. var timerLogger = this.loggerFactory.CreateLogger <AsyncTaskSafeTimer>(); this.renewLeaseTimer = new AsyncTaskSafeTimer(timerLogger, this.MaintainAndBalanceQueues, null, this.siloMaturityPeriod, this.leaseLength.Divide(2)); //try to acquire maximum leases every leaseLength this.tryAcquireMaximumLeaseTimer = new AsyncTaskSafeTimer(timerLogger, this.AcquireLeaseToMeetMaxResponsibilty, null, this.siloMaturityPeriod, this.leaseLength); //Selector default to round robin selector now, but we can make a further change to make selector configurable if needed. Selector algorithm could //be affecting queue balancing stablization time in cluster initializing and auto-scaling this.queueSelector = new RoundRobinSelector <QueueId>(this.allQueues); return(MaintainAndBalanceQueues(null)); }
internal void NextSelectionWontGoInfinitely(List <string> resources, IResourceSelector <string> resourceSelector) { Assert.Equal(resources.Distinct().Count(), resources.Count); resources.Sort(); List <string> selected = resourceSelector.NextSelection(int.MaxValue, new List <string>()); Assert.Equal(resources.Count, selected.Count); selected = selected.Distinct().ToList(); selected.Sort(); Assert.Equal(resources.Count, selected.Count); for (int i = 0; i < selected.Count; i++) { Assert.Equal(resources[i], selected[i]); } }
/// <inheritdoc/> public override Task Initialize(IStreamQueueMapper queueMapper) { if (base.Cancellation.IsCancellationRequested) { throw new InvalidOperationException("Cannot initialize a terminated balancer."); } if (queueMapper == null) { throw new ArgumentNullException("queueMapper"); } this.allQueues = new ReadOnlyCollection <QueueId>(queueMapper.GetAllQueues().ToList()); //Selector default to round robin selector now, but we can make a further change to make selector configurable if needed. Selector algorithm could //be affecting queue balancing stablization time in cluster initializing and auto-scaling this.queueSelector = new RoundRobinSelector <QueueId>(this.allQueues, new Random(this.GetHashCode())); return(base.Initialize(queueMapper)); }
/// <inheritdoc/> public override Task Initialize(IStreamQueueMapper queueMapper) { if (queueMapper == null) { throw new ArgumentNullException("queueMapper"); } this.allQueues = new ReadOnlyCollection <QueueId>(queueMapper.GetAllQueues().ToList()); if (this.allQueues.Count == 0) { return(Task.CompletedTask); } this.leaseProvider = this.serviceProvider.GetRequiredService(options.LeaseProviderType) as ILeaseProvider; NotifyAfterStart().Ignore(); //make lease renew frequency to be every half of lease time, to avoid renew failing due to timing issues, race condition or clock difference. ITimerRegistry timerRegistry = this.serviceProvider.GetRequiredService <ITimerRegistry>(); this.renewLeaseTimer = timerRegistry.RegisterTimer(null, this.MaintainAndBalanceQueues, null, this.options.SiloMaturityPeriod, this.options.LeaseLength.Divide(2)); //try to acquire maximum leases every leaseLength this.tryAcquireMaximumLeaseTimer = timerRegistry.RegisterTimer(null, this.AcquireLeaseToMeetMaxResponsibility, null, this.options.SiloMaturityPeriod, this.options.SiloMaturityPeriod); //Selector default to round robin selector now, but we can make a further change to make selector configurable if needed. Selector algorithm could //be affecting queue balancing stablization time in cluster initializing and auto-scaling this.queueSelector = new RoundRobinSelector <QueueId>(this.allQueues); return(MaintainAndBalanceQueues(null)); }
/// <summary> /// Sets a resource selector for the current CallContext. /// </summary> /// <param name="resourceSelector">The resource selector to be used in the current CallContext.</param> IResourceSelector IHasContextualResourceSelector.SetContextualResourceSelector(IResourceSelector resourceSelector) { CallContext.SetData(ResourceSelectorKey, resourceSelector); return(DefaultResourceSelector); }
public RoundRobinSelectorTests(ITestOutputHelper output) : base(output) { this.resources = Enumerable.Range(0, ResourceCount).Select(i => $"resource_{i}").ToList(); this.resourceSelector = new RoundRobinSelector <string>(this.resources); }
internal void NextSelectionWontReSelectExistingSelections(List <string> resources, IResourceSelector <string> resourceSelector) { Assert.Equal(resources.Distinct().Count(), resources.Count); for (int selectCount = 0; selectCount < resources.Count; selectCount++) { for (int excludeCount = 0; excludeCount < resources.Count; excludeCount++) { List <string> excluded = resourceSelector.NextSelection(excludeCount, new List <string>()); Assert.Equal(excludeCount, excluded.Count); excluded = excluded.Distinct().ToList(); Assert.Equal(excludeCount, excluded.Count); List <string> selected = resourceSelector.NextSelection(selectCount, excluded); int expectedCount = Math.Min(selectCount, resources.Count - excludeCount); Assert.Equal(expectedCount, selected.Count); selected = selected.Distinct().ToList(); Assert.Equal(expectedCount, selected.Count); for (int i = 0; i < selected.Count; i++) { Assert.DoesNotContain(selected[i], excluded); } } } }
internal void NextSelectionWillGoThroughEveryResourceIfExistingSelectionEmpty(List <string> resources, IResourceSelector <string> resourceSelector) { Assert.Equal(resources.Distinct().Count(), resources.Count); resources.Sort(); List <string> selected = resourceSelector.NextSelection(resources.Count, new List <string>()); Assert.Equal(resources.Count, selected.Count); selected = selected.Distinct().ToList(); selected.Sort(); Assert.Equal(resources.Count, selected.Count); for (int i = 0; i < selected.Count; i++) { Assert.Equal(resources[i], selected[i]); } }