- SocketException:通常只允许使用一个套接字地址(协议/网络地址/端口)

本文关键字:一个 套接字 协议 端口 网络地址 地址 SocketException 许使用 | 更新日期: 2023-09-27 18:07:11

由于某种原因,我在多线程环境下在Redis dB中批量创建键。NET MVC Web应用程序。
我在用ServiceStack。Redis for Redis client.

我创建了一个静态类,用于所有必需的redis操作,即put,get..
在那个静态类中,我为每个调用创建了一个新的redis实例,一旦调用完成(使用使用)
代码如下:

for (int i = 0; i < 100000; i++)
                {
                    using (RedisClient Client = new RedisClient(_ReplicaHost))
                    {
                        Client.AddItemToSet(key, value);
                    } 
                }

然而,一段时间后,我得到以下错误:

ServiceStack.Redis.RedisException: could not connect to redis Instance at xxx-xxx.xxxx.0001.use1.cache.amazonaws.com:6379 ---> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted xxx.xx.x.xxx:6379
   at System.Net.Sockets.Socket.Connect(IPAddress[] addresses, Int32 port)
   at System.Net.Sockets.Socket.Connect(String host, Int32 port)
   at ServiceStack.Redis.RedisNativeClient.Connect()

我查看了一下网络,发现可能的原因是套接字耗尽(参考)

由于应用程序在多线程环境下运行,我必须使用PooledRedisClientManagerBasicRedisClientManager中的任何一个,但我不确定在我的情况下选择哪一个,以及如何实现,无论多个操作,都不应该有套接字耗尽的任何问题。

正确的方法/解决方案应该是什么?

- SocketException:通常只允许使用一个套接字地址(协议/网络地址/端口)

不要在循环的每次迭代中为Redis Client创建一个新的实例。使用Redis Manager来解析Redis Client实例,例如:

var redisManager = new RedisManagerPool();
for (int i = 0; i < 100000; i++)
{
    using (RedisClient Client = redisManager.GetClient())
    {
        Client.AddItemToSet(key, value);
    } 
}

但是没有理由为什么你需要一个新的客户端每次迭代,应该只使用相同的RedisClient实例,如果这是真正的代码。

你只有有限数量的端口可用在您的机器上所有进程之间共享,发送和接收网络数据(确切地说是65535)-当你做出一个出站连接绑定到本地端口(即使你只指定一个远程端口你仍然使用本地端口),鉴于你只有65535和100000次迭代我建议你是饥饿的套接字的机器资源并没有给它任何时候收回这些端口。

也许你应该只有一个Redis客户端并在其中循环:

using (RedisClient Client = new RedisClient(_ReplicaHost))
{
    for (int i = 0; i < 100000; i++)
    {
        Client.AddItemToSet(key, value);
    } 
}