Reputation: 7232
When my application traffic gets high, StackExchange.Redis
starts to throw RedisTimeoutException
and after some minutes, my asp.net core application crashes.
The Windows event viewer says The process was terminated due to an unhandled exception. Exception Info: StackExchange.Redis.RedisTimeoutException
.
Ok, I understand that there is some issue between my app and Redis, but while I can't solve this, how can I prevent the application to shutdown?
Inside startup.cs
, I tried to put:
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
eventArgs.Exception.Handle(ex => true);
};
no success....
Any help ?
Tks
Upvotes: 11
Views: 1562
Reputation: 4549
I agree with @thepirat000's answer, reason is ConnectionMultiplexer
You can use ConnectionMultiplexer according your Redis package (StackExchange.Redis or ServiceStack.Redis) and according your deployment environment
In my aspnet core application (like you) i have used StackExchange.Redis and i have deployed to windows server without any error within below Startup.cs settings
#region Redis settings ConnectionMultiplexer
services.AddDataProtection().ProtectKeysWithDpapi(protectToLocalMachine: true);
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp-keys"))
.ProtectKeysWithDpapiNG($"CERTIFICATE=HashId:{thumbPrint}", flags: Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags.None);
services.AddDataProtection().ProtectKeysWithDpapiNG();
services.Configure<StorageConfiguration>(new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json", optional: true, reloadOnChange: true).Build());
var redisConf = Configuration.GetSection("RedisConnection").Get<RedisConnection>();
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(redisConf.Host.ToString() + ":" + redisConf.Port.ToString());
services.AddDataProtection().PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");
services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect(redisConf.Host.ToString() + ":" + redisConf.Port.ToString()));
#endregion
Look here for basic usage https://stackexchange.github.io/StackExchange.Redis/Basics.html
Upvotes: 1
Reputation: 13124
How are you creating the ConnectionMultiplexer
instances?
Maybe you are not reusing a multiplexer instance and creating a lot of connections.
The ConnectionMultiplexer
object should be shared and reused between callers. It is not recommended to create a ConnectionMultiplexer
per operation. Check StackExchange.Redis documentation here for more information.
About the exception handling on Asp.NET Core, you can use the UseExceptionHandler
diagnostic middleware to handle exceptions globally. Check this article for a complete explanation
Upvotes: 3
Reputation: 996
Have you tried to put the block that throws the exception in a try/catch block? And perhaps make it try a few times with Polly when there is a timeout. https://github.com/App-vNext/Polly
Normally it shouldn't terminate your app, but since you didn't share any code, We can not be sure.
If you create a service class like below, you can encapsulate all of your redis calls, therefore catch the exceptions.
public class EmptyClass
{
private readonly ConnectionMultiplexer _connectionMultiplexer;
public EmptyClass(ConnectionMultiplexer connectionMultiplexer)
{
_connectionMultiplexer = connectionMultiplexer;
}
public void Execute(Action<ConnectionMultiplexer> action)
{
try
{
action.Invoke(_connectionMultiplexer);
}
catch(RedisTimeoutException ex)
{
}
}
public void TestRun()
{
Execute((ConnectionMultiplexer obj) =>
{
//do stuff with obj.
});
}
}
Upvotes: 3