我需要获取我当前连接的所有主机的列表。这应该很简单:
private IEnumerable<IServer> Masters => connection
.GetEndPoints()
.Select(e => connection.GetServer(e))
.Where(s => !s.IsSlave);
这在本地有效,但在我们连接集群的生产环境中,它会返回重复的主节点并搞砸我的代码。这样做的原因是我们的连接字符串是“RedisServer1:7000,RedisServer2:7000”,所以我们得到一个 EndPoint,它是一个带有 RedisServer1 的 DnsEndPoint,和一个 EndPoint,它是一个 IPEndPoint,它是 10.0.0.15(或一些 IP),因为它是使用集群中的所有内容。这两个端点实际上指向同一个盒子。所以,我想我可以这样做:
private IEnumerable<IServer> Masters => connection
.GetEndPoints()
.Where(e => e is IPEndPoint)
.Select(e => connection.GetServer(e))
.Where(s => !s.IsSlave);
这修复了生产,所以我不再有傻瓜。但是,我们的功能测试随后中断,因为它们使用的是非集群的单个 Redis 实例,它只是“localhost”的 DnsEndpoint。
我可能可以使用某种“分组依据”并过滤掉重复项,但是 DnsEndpoints 有主机名而 IPEndPoints 有 IP 地址,所以没有真的一种方法来判断两个端点是相同的。我一直在寻找某种全局唯一的“Redis 实例 ID”之类的东西,但似乎没有这样的东西。也许我能以某种方式判断我是否已连接到集群并基于此更改我的逻辑?
解决此问题的最佳方法是什么?
更新:为了阐明我的意思,如果我有一个在本地主机上运行的 6 节点集群,GetEndPoints()
将返回 7 个东西:
(数组元素0和4是一回事)
最佳答案
我认为这不是一个完美的答案,但这是我想出的:
private IEnumerable<EndPoint> Endpoints
{
get
{
EndPoint[] endpoints = connection.GetEndPoints();
IServer firstServer = connection.GetServer(endpoints.FirstOrDefault());
return firstServer?.ServerType == ServerType.Cluster ? firstServer.ClusterConfiguration.Nodes.Select(n => n.EndPoint) : endpoints;
}
}
private IEnumerable<IServer> Masters => Endpoints
.Select(e => connection.GetServer(e))
.Where(s => !s.IsSlave);
基本上,我会在第一个端点查看服务器。如果该服务器是集群的一部分,我将返回集群中的所有节点。否则,我只返回所有端点。
如果您的端点指向多个集群,或者指向集群和独立实例的混合,则此解决方案存在理论上的缺陷。不过,我真的希望没有人这样做。
如果您的端点为零,它也可能会使用更多的空值检查。
关于c# - 如何使用 GetEndPoints() 获取唯一端点列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49702710/