9
votes

RedisTimeoutException plante mon application principale aspnet

Lorsque le trafic de mon application devient élevé, StackExchange.Redis commence à lancer RedisTimeoutException et après quelques minutes, mon application principale asp.net se bloque.
L'observateur d'événements Windows indique que The process was terminated due to an unhandled exception. Exception Info: StackExchange.Redis.RedisTimeoutException . OK, je comprends qu'il y a un problème entre mon application et Redis, mais même si je ne peux pas résoudre ce problème, comment puis-je empêcher l'application de s'arrêter?

Dans startup.cs , j'ai essayé de mettre:

TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
    eventArgs.SetObserved();
    eventArgs.Exception.Handle(ex => true);
};

Sans succès....

De l'aide ?

Tks


0 commentaires

3 Réponses :


3
votes

Avez-vous essayé de placer le bloc qui lève l'exception dans un bloc try / catch? Et peut-être faites-le essayer plusieurs fois avec Polly lorsqu'il y a un délai d'attente. https://github.com/App-vNext/Polly

Normalement, cela ne devrait pas mettre fin à votre application, mais comme vous n'avez partagé aucun code, nous ne pouvons pas en être sûrs.

Si vous créez une classe de service comme ci-dessous, vous pouvez encapsuler tous vos appels redis, donc intercepter les 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.
        });
    }
}


0 commentaires

2
votes

Comment créez-vous les instances ConnectionMultiplexer ?

Peut-être que vous ne réutilisez pas une instance de multiplexeur et ne créez pas beaucoup de connexions.

L'objet ConnectionMultiplexer doit être partagé et réutilisé entre les appelants. Il n'est pas recommandé de créer un ConnectionMultiplexer par opération. Consultez la documentation de StackExchange.Redis ici pour plus d'informations.

À propos de la gestion des exceptions sur Asp.NET Core, vous pouvez utiliser le middleware de diagnostic UseExceptionHandler pour gérer les exceptions globalement. Consultez cet article pour une explication complète


6 commentaires

Hey! Nous avons corrigé cela, maintenant nous utilisons la stratégie de pool et tout va bien, mais la question principale est: Comment éviter le crash de l'application?


Attraper les exceptions. Vérifiez ceci etcela . Et @Ahmet répond


Existe-t-il un moyen d'attraper globalement les exceptions redis dans aspnet core?


@Alexandre J'ai ajouté un moyen d'attraper toutes les exceptions de délai d'attente Redis globalement à ma réponse.


@Alexandre vous pouvez utiliser un gestionnaire d'exceptions global. Vérifiez ceci


Tks! Étant donné que la question ne concerne pas les redis stackexchange, vous devez modifier votre réponse en indiquant l'exception globale. Ensuite, je marquerai comme répondu :)



1
votes

Je suis d'accord avec la réponse de @ thepirat000, la raison est ConnectionMultiplexer

Vous pouvez utiliser ConnectionMultiplexer selon votre package Redis (StackExchange.Redis ou ServiceStack.Redis) et selon votre environnement de déploiement

Dans mon application principale aspnet (comme vous), j'ai utilisé StackExchange.Redis et j'ai déployé sur le serveur Windows sans aucune erreur dans les paramètres de Startup.cs ci-dessous

        #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

Regardez ici pour l'utilisation de basehttps://stackexchange.github.io/StackExchange.Redis/Basics.html


0 commentaires