使用.Net核心的ServiceStack RedisAWS ElastiCache实现导致错误在以下位置找不到主服务器:redis-cluster-xxxxxxxx:637

如何解决使用.Net核心的ServiceStack RedisAWS ElastiCache实现导致错误在以下位置找不到主服务器:redis-cluster-xxxxxxxx:637

我已经实现了以下版本的ServiceStack .net Core Redis库:

ServiceStack.Redis.Core 5.9.2

我正在使用该库访问我创建的Redis缓存,以使用.NET Core 3.1持久保存我的AWS Serverless Application的值。我已经为ServiceStack Redis支付了商业许可。

我的应用程序会定期且无警告地尝试创建Redis客户端时捕获以下错误

Exception: System.Exception: No master found in: redis-cluster-api-prd-lcs.in-xxxxxxxx:6379
   at ServiceStack.Redis.RedisResolver.CreateRedisClient(RedisEndpoint config,Boolean master) in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisResolver.cs:line 116
   at ServiceStack.Redis.RedisResolver.CreateMasterClient(Int32 desiredindex) in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisResolver.cs:line 142
   at ServiceStack.Redis.RedisManagerPool.GetClient() in C:\BuildAgent\work\b2a0bfe2b1c9a118\src\ServiceStack.Redis\RedisManagerPool.cs:line 174
   at LCSApi.UtilityCommand.Cache.IsCacheValueExists(String cacheKey,RedisManagerPool pool) in D:\a\1\s\testapi\Utility.cs:line 167
   at LCSApi.Functions.LcsConfigurationsweeper(ILambdaContext context) in D:\a\1\s\testapi\Function.cs:line 2028
Exception: System.Exception: No master found in: redis-cluster-api-prd-lcs.in

其他时候,相同的代码也可以正常工作。我的实现非常简单:

private readonly RedisManagerPool _redisClient;

 _redisClient = new RedisManagerPool(Environment.GetEnvironmentvariable("CACHE_URL") + ":" +
Environment.GetEnvironmentvariable("CACHE_PORT"));

        public static T GetCacheValue<T>(string cacheKey,RedisManagerPool pool)
        {
            T cacheValue;

            try
            {
                //StackExchange.Redis.IDatabase cache = Functions._redisConnect.GetDatabase();
                //string value = cache.StringGet(cacheKey);
                //cacheValue = (T)Convert.ChangeType(value,typeof(T));
                using (var client = pool.GetClient())
                {
                    client.RetryCount = Convert.ToInt32(Environment.GetEnvironmentvariable("CACHE_RETRY_COUNT"));
                    client.RetryTimeout = Convert.ToInt32(Environment.GetEnvironmentvariable("CACHE_RETRY_TIMEOUT"));
                    cacheValue = client.Get<T>(cacheKey);
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine($"[CACHE_EXCEPTION] {ex.ToString()}");
                cacheValue = GetParameteRSSMFallback<T>(cacheKey);
                //Console.WriteLine($"[CACHE_EXCEPTION] Fallback SSM parameter --> {cacheValue}");
            }

            return cacheValue;
        }

发生了足够多的事情,我不得不编写一个“后备”例程来从其起源的AWS参数存储中获取值。不理想。这是Redis配置:

enter image description here

我几乎可以在任何地方在线找到关于此错误的信息。我曾尝试注册ServiceStack论坛,但未成功,尽管我已经获得了商业许可,但由于某些原因,它不允许我注册。谁能帮忙?

解决方法

该错误是由于网络实例未连接到redis ROLE命令所标识的主实例。 during an ElastiCache failover可能会发生这种情况,最终似乎主实例将以原始DNS名称返回:

Amazon ElastiCache for Redis将通过获取新的服务资源来修复该节点,然后将重定向该节点的现有DNS名称以指向新的服务资源。因此,Redis节点的DNS名称保持不变,但是Redis节点的IP地址会随时间变化。

ServiceStack.Redis将尝试使用所有指定的主连接(通常只有1个)连接到主实例。如果无法连接到主实例,则必须放弃,因为客户端希望对读/写主实例执行操作。

如果可以预期,主实例将以相同的DNS名称返回,则可以使用自定义IRedisResolver在指定的时间段内连续重试主实例在同一连接上的连接,例如:

public class ElasticCacheRedisResolver : RedisResolver 
{
    public override RedisClient CreateRedisClient(RedisEndpoint config,bool master)
    {
        if (master)
        {
            //ElastiCache Redis will failover & retain same DNS for master
            var firstAttempt = DateTime.UtcNow;
            Exception firstEx = null;
            var retryTimeSpan = TimeSpan.FromMilliseconds(config.RetryTimeout);
            var i = 0;
            while (DateTime.UtcNow - firstAttempt < retryTimeSpan) {
                try
                {
                    var client = base.CreateRedisClient(config,master:true);
                    return client;
                }
                catch (Exception ex)
                {
                    firstEx ??= ex;
                    ExecUtils.SleepBackOffMultiplier(++i);
                }
            }
            throw new TimeoutException(
              $"Could not resolve master within {config.RetryTimeout}ms RetryTimeout",firstEx);
        }
        return base.CreateRedisClient(config,master:false);
    }
}

使用Redis客户端管理器进行配置,例如:

private static readonly RedisManagerPool redisManager;

redisManager = new RedisManagerPool(...) {
    RedisResolver = new ElasticCacheRedisResolver()
};

注意:在那里,您应该仅使用Redis Client Managers的1个共享实例,例如RedisManagerPool,以便共享同一连接池。如果包含redisManager的类不是单例,则应将其分配给一个静态字段,以确保使用相同的单例实例来检索客户端。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?