Load Balance / Webfarm support version 4.20 - Help please

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
4 years ago
Hello,
I have two servers sat behind a load balancer. I have a shared database instance and redis 5 connected.
What is the best solution to load balance this? It seems to me that I need to share the following folders between these two instances?
/Themes
/Plugins
/App_data

Any help would be appreciated.
4 years ago
Hi Ian,
I can share what we've done:
1. Create a shared folder for /app_data; /wwwroot/files; /wwwroot/images; /wwwroot/icons  - you can use a symlink to that shared folder and aspnet core will not know the difference.
2. Use Redis for caching and storing plugins info (see settings in appSettings.json).  Enable (set to true) RedisEnabled, UseRedisToStoreDataProtectionKeys, UseRedisToStorePluginsInfo, UseRedisForCaching and UseSessionStateTempDataProvider - if you want the details on why, see this article: https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/web-farm?view=aspnetcore-2.2
Set a database ID for the caching and pluginsinfo in the appSettings RedisDatabaseId field.
3. Create a plugin to add a NopStartup file. Set the database ID for the connection string to a different ID than above - you want to keep your session keys and your cache keys separate:

    public class MyNopStartup : INopStartup
    {
        public int Order => 0; //add early on

        public void Configure(IApplicationBuilder application)
        {
        }
        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            var nopSection = configuration.GetSection("Nop");   //pull from appsettings.config. Can't use NopConfig here - NopStartups get loaded before dependency injection
            var redisEnabled = bool.Parse(configuration["Nop:RedisEnabled"]);
            var redisConn = configuration["Nop:RedisConnectionString"] + ",defaultDatabase=2";
            if (redisEnabled && !string.IsNullOrEmpty(redisConn))
            {
                //THIS DOES NOT ENABLE REDIS CACHE. THIS ALLOWS SESSION TO USE REDIS AS A SESSION PROVIDER.
                services.AddDistributedRedisCache(o =>
                {
                    o.Configuration = redisConn;
                });
            }
        }
    }

This article talks about how to enable Redis as a session provider for asp.net core and explains why we have to do this: https://dotnetthoughts.net/configuring-redis-for-aspnet-core-session-store/

NOP already does the AddSession() and UseSession() call - so all you have to do is add the AddDistributedRedisCache() call using a NopStartup class.

In this plugin you'll need a reference to  Microsoft.Extensions.Caching.Redis Version 2.2.0 - pull from nuget. In your csproj file make sure to enable
    <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
or the library will not be copied and you'll get a runtime error that the package is missing.

Good luck.
4 years ago
Hello,

I actually tried moving the entire nopCommerce folder including its subfolders (app_data etc) to a NAS drive.  I created a symlink, It started up ok, then I added plugins.  On restart I got "System.BadImageFormatException: Bad IL format." on each plugin.  Which I find is really strange given the nopCommerce files are also on the nas drive and yet these don't show an error, only the plugins.

Any ideas?
3 years ago
Hi Walter,
Can you clarify how you created your symlink for those folders?  I'm trying this same solution but when set up a symlink I get an error at startup

System.IO.DirectoryNotFoundException: C:\inetpub\wwwroot\wwwroot\images\uploaded\

my symlink was created using
mklink /D [local path] [network path]

WalterG-BAS wrote:

I can share what we've done:
1. Create a shared folder for /app_data; /wwwroot/files; /wwwroot/images; /wwwroot/icons  - you can use a symlink to that shared folder and aspnet core will not know the difference.
3 years ago
After a little tinkering I was able to figure out what was missing from my symlink setup.  For anyone else attempting the solution that Walter mentioned, here are a few extra details based on what I had to do to make it work.

The issue boiled down to permissions of the network share, and I wasn't able to provide the default "ApplicationPoolIdentity" with the necessary permissions.  To resolve this I did the following

1. Created a specific user on the web server and set the application pool to use this new user.
2. In the advanced settings of the application pool, set "Load User Profile" to "True"
3. Add the credentials for the network share to the user created for the application pool.  This post helped https://superuser.com/questions/537697/manage-another-users-credentials-for-network-access.  Alternatively if you log into the server using the new app pool user, navigate to the network share path and when it prompts for credentials enter them and select the option to remember them.
4. create your symlinks to the network share folders using mklink command.
2 years ago
We've been working on a feature to allow a Hybrid Cache so that you get the performance of having a local cache, but can keep it synchronized via a Redis backplane. This has a huge performance gain versus using straight Redis cache.

If you have these problems and are trying to solve them, BuildASign has agreed to open source our plugin for the general community.
You can download it on GitHub here: https://github.com/buildasign/nop-hybrid-cache

The Readme.md file has instructions.
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.