Exemplo n.º 1
0
        /// <summary>
        /// Implements a callback delegate which will be invoked whenever there is no more work available on the queue.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="idleCount">The value indicating how many times the queue listener has been idle.</param>
        /// <param name="delay">The time interval during which the queue listener will be instructed to sleep before performing next unit of work.</param>
        /// <returns>A boolean flag indicating that the queue listener should stop processing any further work and must terminate.</returns>
        private bool HandleQueueEmptyEvent(object sender, int idleCount, out TimeSpan delay)
        {
            // The sender is an instance of the ICloudQueueServiceWorkerRoleExtension, we can safely perform type casting.
            ICloudQueueServiceWorkerRoleExtension queueService = sender as ICloudQueueServiceWorkerRoleExtension;

            // Find out which extension is responsible for retrieving the worker role configuration settings.
            IWorkItemProcessorConfigurationExtension config = Extensions.Find <IWorkItemProcessorConfigurationExtension>();

            // Get the current state of the queue listener to determine point-in-time load characteristics.
            CloudQueueListenerInfo queueServiceState = queueService.QueryState();

            // Set up the initial parameters, read configuration settings.
            int deltaBackoffMs        = 100;
            int minimumIdleIntervalMs = Convert.ToInt32(config.Settings.MinimumIdleInterval.TotalMilliseconds);
            int maximumIdleIntervalMs = Convert.ToInt32(config.Settings.MaximumIdleInterval.TotalMilliseconds);

            // Calculate a new sleep interval value that will follow a random exponential back-off curve.
            int delta    = (int)((Math.Pow(2.0, (double)idleCount) - 1.0) * (new Random()).Next((int)(deltaBackoffMs * 0.8), (int)(deltaBackoffMs * 1.2)));
            int interval = Math.Min(minimumIdleIntervalMs + delta, maximumIdleIntervalMs);

            // Pass the calculated interval to the dequeue task to enable it to enter into a sleep state for the specified duration.
            delay = TimeSpan.FromMilliseconds((double)interval);

            // As soon as interval reaches its maximum, tell the source dequeue task that it must gracefully terminate itself
            // unless this is a last deqeueue task. If so, we are not going to keep it running and continue polling the queue.
            return(delay.TotalMilliseconds >= maximumIdleIntervalMs);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Notifies this extension component that it has been registered in the owner's collection of extensions.
        /// </summary>
        /// <param name="owner">The extensible owner object that aggregates this extension.</param>
        public void Attach(IExtensibleCloudServiceComponent owner)
        {
            owner.Extensions.Demand <IWorkItemProcessorConfigurationExtension>();
            owner.Extensions.Demand <IRoleConfigurationSettingsExtension>();
            owner.Extensions.Demand <ICloudCacheProviderExtension>();
            owner.Extensions.Demand <IRulesEngineServiceClientExtension>();

            this.configSettingsExtension = owner.Extensions.Find <IWorkItemProcessorConfigurationExtension>();
            this.roleConfigExtension     = owner.Extensions.Find <IRoleConfigurationSettingsExtension>();
            this.cacheProviderExtension  = owner.Extensions.Find <ICloudCacheProviderExtension>();
            this.rulesEngineExtension    = owner.Extensions.Find <IRulesEngineServiceClientExtension>();
        }
Exemplo n.º 3
0
        private void HandlePersistenceQueueItem(PersistenceQueueItemInfo itemInfo)
        {
            Guard.ArgumentNotNull(itemInfo, "itemInfo");

            var callToken = TraceManager.WorkerRoleComponent.TraceIn(itemInfo.QueueItemId, itemInfo.QueueItemType, itemInfo.QueueItemSize);

            try
            {
                this.owner.Extensions.Demand <IRulesEngineServiceClientExtension>();
                this.owner.Extensions.Demand <IWorkItemProcessorConfigurationExtension>();

                IWorkItemProcessorConfigurationExtension configSettingsExtension = this.owner.Extensions.Find <IWorkItemProcessorConfigurationExtension>();
                IRulesEngineServiceClientExtension       rulesEngineExtension    = this.owner.Extensions.Find <IRulesEngineServiceClientExtension>();

                // Invoke a policy to determine the number of dequeue listeners required to process this volume of data.
                StringDictionaryFact policyExecutionResult = rulesEngineExtension.ExecutePolicy <StringDictionaryFact>(configSettingsExtension.Settings.HandlingPolicyName, itemInfo);
                int dequeueTaskCount = policyExecutionResult != null && !String.IsNullOrEmpty(policyExecutionResult.Items[Resources.StringDictionaryFactValueDequeueListenerCount]) ? Convert.ToInt32(policyExecutionResult.Items[Resources.StringDictionaryFactValueDequeueListenerCount]) : 0;

                // Check if the policy has provided us with the number of queue listeners.
                if (dequeueTaskCount > 0)
                {
                    // Write the number of dequeue tasks into trace log.
                    TraceManager.WorkerRoleComponent.TraceInfo(TraceLogMessages.DequeueTaskCountInfo, itemInfo.QueueItemType, itemInfo.QueueItemSize, dequeueTaskCount);

                    // Request all queue listeners to increase the number of listeners accordingly to the given workload.
                    foreach (var queueService in this.owner.Extensions.FindAll <ICloudQueueServiceWorkerRoleExtension>())
                    {
                        // Get the queue listener state information such as queue depth, number of activity listener threads and total number of listener threads.
                        var state = queueService.QueryState();

                        // If the queue listener count is less than suggested by the policy, start as many extra listener threads as needed.
                        if (state.ActiveDequeueTasks < dequeueTaskCount)
                        {
                            queueService.StartListener(dequeueTaskCount - state.ActiveDequeueTasks);
                        }
                    }
                }
            }
            finally
            {
                TraceManager.WorkerRoleComponent.TraceOut(callToken);
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Extends the OnStart phase that is called by Windows Azure runtime to initialize the role instance.
        /// </summary>
        /// <returns>True if initialization succeeds, otherwise false.</returns>
        protected override bool OnRoleStart()
        {
            this.EnsureExists <WorkItemProcessorConfigurationExtension>();
            this.EnsureExists <WorkQueueLocationResolverExtension>();
            this.EnsureExists <ScalableTransformServiceClientExtension>();
            this.EnsureExists <EndpointConfigurationDiscoveryExtension>();
            this.EnsureExists <RulesEngineServiceClientExtension>();
            this.EnsureExists <InterRoleEventSubscriberExtension>();

            IWorkItemProcessorConfigurationExtension configSettingsExtension = Extensions.Find <IWorkItemProcessorConfigurationExtension>();
            IEndpointConfigurationDiscoveryExtension discoveryExtension      = Extensions.Find <IEndpointConfigurationDiscoveryExtension>();
            IInterRoleCommunicationExtension         interCommExtension      = Extensions.Find <IInterRoleCommunicationExtension>();
            IInterRoleEventSubscriberExtension       interCommSubscriber     = Extensions.Find <IInterRoleEventSubscriberExtension>();

            CloudQueueLocation inputQueueLocation = new CloudQueueLocation()
            {
                StorageAccount    = configSettingsExtension.Settings.CloudStorageAccount,
                QueueName         = configSettingsExtension.Settings.WorkItemQueue,
                VisibilityTimeout = configSettingsExtension.Settings.WorkItemQueueVisibilityTimeout
            };

            CloudQueueLocation outputQueueLocation = new CloudQueueLocation()
            {
                StorageAccount    = configSettingsExtension.Settings.CloudStorageAccount,
                QueueName         = configSettingsExtension.Settings.OutputQueue,
                VisibilityTimeout = configSettingsExtension.Settings.OutputQueueVisibilityTimeout
            };

            // Instantiate queue listeners.
            var inputQueueListener  = new CloudQueueListenerExtension <XDocument>(inputQueueLocation);
            var outputQueueListener = new CloudQueueListenerExtension <XDocument>(outputQueueLocation);

            // Configure the input queue listener.
            inputQueueListener.QueueEmpty      += HandleQueueEmptyEvent;
            inputQueueListener.DequeueBatchSize = configSettingsExtension.Settings.DequeueBatchSize;
            inputQueueListener.DequeueInterval  = configSettingsExtension.Settings.MinimumIdleInterval;

            // Configure the output queue listener.
            outputQueueListener.QueueEmpty      += HandleQueueEmptyEvent;
            outputQueueListener.DequeueBatchSize = configSettingsExtension.Settings.DequeueBatchSize;
            outputQueueListener.DequeueInterval  = configSettingsExtension.Settings.MinimumIdleInterval;

            // Instantiate queue subscribers.
            InputQueueSubscriberExtension  inputQueueSubscriber  = new InputQueueSubscriberExtension();
            OutputQueueSubscriberExtension outputQueueSubscriber = new OutputQueueSubscriberExtension();

            // Register subscribers with queue listeners.
            inputQueueListener.Subscribe(inputQueueSubscriber);
            outputQueueListener.Subscribe(outputQueueSubscriber);

            // Register custom extensions for this worker role.
            Extensions.Add(inputQueueSubscriber);
            Extensions.Add(outputQueueSubscriber);
            Extensions.Add(outputQueueListener);
            Extensions.Add(inputQueueListener);

            var contractTypeMatchCondition = ServiceEndpointDiscoveryCondition.ContractTypeExactMatch(typeof(IScalableTransformationServiceContract));
            var bindingTypeMatchCondition  = ServiceEndpointDiscoveryCondition.BindingTypeExactMatch(typeof(NetTcpRelayBinding));

            discoveryExtension.RegisterDiscoveryAction(new[] { contractTypeMatchCondition, bindingTypeMatchCondition }, (endpoint) =>
            {
                NetTcpRelayBinding relayBinding = endpoint.Binding as NetTcpRelayBinding;
                if (relayBinding != null)
                {
                    relayBinding.TransferMode = TransferMode.Streamed;
                }
            });

            // Register a subscriber for all inter-role communication events.
            if (interCommExtension != null && interCommSubscriber != null)
            {
                this.interCommSubscription = interCommExtension.Subscribe(interCommSubscriber);
            }

            return(true);
        }
Exemplo n.º 5
0
 /// <summary>
 /// Notifies this extension component that it has been registered in the owner's collection of extensions.
 /// </summary>
 /// <param name="owner">The extensible owner object that aggregates this extension.</param>
 public void Attach(IExtensibleCloudServiceComponent owner)
 {
     this.configSettingsExtension = owner.Extensions.Find <IWorkItemProcessorConfigurationExtension>();
 }