U4-10150 Process load balancing instructions on a background thread instead of a request thread

This commit is contained in:
Shannon
2017-10-31 15:11:45 +11:00
parent 2fdd1c0bd2
commit 0038d173a2
3 changed files with 63 additions and 18 deletions

View File

@@ -205,7 +205,7 @@ namespace Umbraco.Core.Sync
/// <summary> /// <summary>
/// Synchronize the server (throttled). /// Synchronize the server (throttled).
/// </summary> /// </summary>
protected void Sync() protected internal void Sync()
{ {
lock (_locko) lock (_locko)
{ {

View File

@@ -9,6 +9,7 @@ using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Sync; using Umbraco.Core.Sync;
using Umbraco.Web.Routing; using Umbraco.Web.Routing;
using Umbraco.Core.Logging; using Umbraco.Core.Logging;
using Umbraco.Web.Scheduling;
namespace Umbraco.Web namespace Umbraco.Web
{ {
@@ -22,7 +23,31 @@ namespace Umbraco.Web
{ {
public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options) public BatchedDatabaseServerMessenger(ApplicationContext appContext, bool enableDistCalls, DatabaseServerMessengerOptions options)
: base(appContext, enableDistCalls, options) : base(appContext, enableDistCalls, options)
{ } {
Scheduler.Initializing += Scheduler_Initializing;
}
/// <summary>
/// Occurs when the scheduler initializes all scheduling activity when the app is ready
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Scheduler_Initializing(object sender, List<IBackgroundTask> e)
{
//if the current resolver is 'this' then we will start the scheduling
var isMessenger = ServerMessengerResolver.HasCurrent && ReferenceEquals(ServerMessengerResolver.Current.Messenger, this);
if (isMessenger)
{
//start the background task runner for processing instructions
const int delayMilliseconds = 60000;
var instructionProcessingRunner = new BackgroundTaskRunner<IBackgroundTask>("InstructionProcessing", ApplicationContext.ProfilingLogger.Logger);
var instructionProcessingTask = new InstructionProcessing(instructionProcessingRunner, this, delayMilliseconds, Options.ThrottleSeconds * 1000);
instructionProcessingRunner.TryAdd(instructionProcessingTask);
e.Add(instructionProcessingTask);
}
}
// invoked by BatchedDatabaseServerMessengerStartup which is an ApplicationEventHandler // invoked by BatchedDatabaseServerMessengerStartup which is an ApplicationEventHandler
// with default "ShouldExecute", so that method will run if app IsConfigured and database // with default "ShouldExecute", so that method will run if app IsConfigured and database
@@ -30,7 +55,6 @@ namespace Umbraco.Web
internal void Startup() internal void Startup()
{ {
UmbracoModule.EndRequest += UmbracoModule_EndRequest; UmbracoModule.EndRequest += UmbracoModule_EndRequest;
UmbracoModule.RouteAttempt += UmbracoModule_RouteAttempt;
if (ApplicationContext.DatabaseContext.CanConnect == false) if (ApplicationContext.DatabaseContext.CanConnect == false)
{ {
@@ -43,20 +67,31 @@ namespace Umbraco.Web
} }
} }
private void UmbracoModule_RouteAttempt(object sender, RoutableAttemptEventArgs e) /// <summary>
/// This will process cache instructions on a background thread and will run every 5 seconds (or whatever is defined in the <see cref="DatabaseServerMessengerOptions.ThrottleSeconds"/>)
/// </summary>
private class InstructionProcessing : RecurringTaskBase
{ {
// as long as umbraco is ready & configured, sync private readonly DatabaseServerMessenger _messenger;
switch (e.Outcome)
public InstructionProcessing(IBackgroundTaskRunner<RecurringTaskBase> runner,
DatabaseServerMessenger messenger,
int delayMilliseconds, int periodMilliseconds)
: base(runner, delayMilliseconds, periodMilliseconds)
{ {
case EnsureRoutableOutcome.IsRoutable: _messenger = messenger;
case EnsureRoutableOutcome.NotDocumentRequest: }
case EnsureRoutableOutcome.NoContent:
Sync(); public override bool PerformRun()
break; {
//case EnsureRoutableOutcome.NotReady: _messenger.Sync();
//case EnsureRoutableOutcome.NotConfigured: //return true to repeat
//default: return true;
// break; }
public override bool IsAsync
{
get { return false; }
} }
} }

View File

@@ -35,7 +35,7 @@ namespace Umbraco.Web.Scheduling
return; return;
// backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly // backgrounds runners are web aware, if the app domain dies, these tasks will wind down correctly
_keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", applicationContext.ProfilingLogger.Logger); _keepAliveRunner = new BackgroundTaskRunner<IBackgroundTask>("KeepAlive", applicationContext.ProfilingLogger.Logger);
_publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", applicationContext.ProfilingLogger.Logger); _publishingRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledPublishing", applicationContext.ProfilingLogger.Logger);
_tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", applicationContext.ProfilingLogger.Logger); _tasksRunner = new BackgroundTaskRunner<IBackgroundTask>("ScheduledTasks", applicationContext.ProfilingLogger.Logger);
_scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", applicationContext.ProfilingLogger.Logger); _scrubberRunner = new BackgroundTaskRunner<IBackgroundTask>("LogScrubber", applicationContext.ProfilingLogger.Logger);
@@ -74,7 +74,7 @@ namespace Umbraco.Web.Scheduling
new KeepAlive(_keepAliveRunner, delayMilliseconds, 300000, e.UmbracoContext.Application), new KeepAlive(_keepAliveRunner, delayMilliseconds, 300000, e.UmbracoContext.Application),
new ScheduledPublishing(_publishingRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings), new ScheduledPublishing(_publishingRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
new ScheduledTasks(_tasksRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings), new ScheduledTasks(_tasksRunner, delayMilliseconds, 60000, e.UmbracoContext.Application, settings),
new LogScrubber(_scrubberRunner, delayMilliseconds, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings), new LogScrubber(_scrubberRunner, delayMilliseconds, LogScrubber.GetLogScrubbingInterval(settings), e.UmbracoContext.Application, settings)
}; };
if (healthCheckConfig.NotificationSettings.Enabled) if (healthCheckConfig.NotificationSettings.Enabled)
@@ -116,10 +116,20 @@ namespace Umbraco.Web.Scheduling
if (healthCheckConfig.NotificationSettings.Enabled) if (healthCheckConfig.NotificationSettings.Enabled)
{ {
_healthCheckRunner.TryAdd(tasks[4]); _healthCheckRunner.TryAdd(tasks[4]);
} }
OnInitializing(tasks);
return tasks.ToArray(); return tasks.ToArray();
}); });
} }
public static event EventHandler<List<IBackgroundTask>> Initializing;
private static void OnInitializing(List<IBackgroundTask> e)
{
var handler = Initializing;
if (handler != null) handler(null, e);
}
} }
} }