Blazor Server IIS Hosting - Not possible to run parallel threads without Web Garden?

51 views Asked by At

A bit of context: In a Blazor Server application, the user can search a database and get back a result with many relations (~15+). We display this result in the UI.

The database is not ours and the database server is way too weak to perform complex selects, so we synchronize the data in a separate service and keep it in a cache. (Several million data records)

When the user now searches, some of the relations are calculated using the cache and assigned to the object. If you build the object one by one, the search takes about 2-4 seconds. Too long. That is why I have swapped the individual assigns to background tasks. Both via classic tasks and an attempt via Parallel.Invoke. The search then takes about 0.3 seconds locally.

Problem: If this code is now deployed on a Windows server via IIS, the tasks are not executed in parallel as in my case, but all in one thread and are executed one after the other. The parallelization on the server does not work.

As I understand it, this is probably due to the fact that the IIS workers are set to 1 and the application is running in an application pool. We cannot increase the workers (Web Garden), as otherwise we would lose the SignalR Session connection and the cache would increase per instance.

Screenshot IIS Worker

With increased workers, it seems like it would work, but we cant increase the worker due to lost of session state, increased memorycache and strange app behaviors.

We have to set it to 1

But how can we run such code in an IIS hosted environment without web garden?

//a small and reduced example of the code
private async Task MyDummySearch()
{
 //load relations in background tasks, due to huge Database.
 //Option 1 - Task.WaitAll()
 Task loadRelationFoo = Task.Run(LoadFoo); //e.g. _myObject.FooProperty = cachedEntityService.GetFoo().Where(x => x.ID == _myObject.FooID) ...
 Task loadRelationBar = Task.Run(LoadBar); //e.g. _myObject.BarProperty = cachedEntityService.GetBar().Where(x => x.ID == _myObject.FooID) ...

 Task.WaitAll(loadRelationFoo, loadRelationBar);

 //Option 2 - Parallel.Invoke
 Parallel.Invoke(LoadFoo, LoadBar);

 //All relations loaded, maybe calculate some stuff, update UI with result
 //local time ~ 350ms
 //server time ~2500 - 3500ms 
}

It seems like I don't quite understand something yet :-)

Thanks for your time and suggestions

0

There are 0 answers