使用 BookSleeve 连接我的 Redis 服务器并向/从我的 Redis 服务器添加/获取条目时,我收到一个 SocketException。具体的例外是:每个套接字地址(协议/网络地址/端口)通常只允许使用一次。
堆栈跟踪指向:BookSleeve.RedisConnectionBase.Wait(Task task) in d:\Dev\BookSleeve\BookSleeve\RedisConnectionBase.cs:2050
我的问题是我是否在我的代码中做错了什么(很可能)没有正确关闭连接或类似的东西?在大约 60 秒内执行约 16000 次操作后,往往会引发异常。这似乎不是一个过于丰富的操作,对吧?
相关代码如下,我很乐意提供任何其他信息。
public Cache.CacheEntry Get(string key, bool updateAccessed)
{
var cacheKey = GetCacheableKey(key);
using (var conn = GetUnsecuredConnection())
{
var entry = conn.Get<Cache.CacheEntry>(cacheKey);
return entry;
}
}
public override void Add(string key, Cache.CacheEntry entry)
{
var cacheKey = GetCacheableKey(key);
using (var conn = GetUnsecuredConnection())
{
using (var trans = conn.CreateTransaction())
{
trans.Set(cacheKey, entry);
trans.Strings.Increment(DbNum, CacheEntryCountKey);
trans.Strings.Increment(DbNum, CacheSizeKey, entry.DataLength);
trans.Sets.Add(DbNum, CacheKeysKey, cacheKey);
trans.Execute();
}
}
}
检索连接(这主要是从 BookSleeve 单元测试中复制的:
protected RedisConnection GetUnsecuredConnection(bool open = true, bool allowAdmin = false, bool waitForOpen = false)
{
var host = ConfigurationManager.AppSettings["Redis.BookSleeve.Host"];
var unsecuredPort = int.Parse(ConfigurationManager.AppSettings["Redis.BookSleeve.UnsecuredPort"]); //TODO: get this setting in a safer manner
var conn = new RedisConnection(host, unsecuredPort, syncTimeout: 5000, ioTimeout: 5000, allowAdmin: allowAdmin);
conn.Error += (s, args) => Log.Error(args.Exception.Message + args.Cause, args.Exception, typeof(RedisProviderBookSleeve));
if (open)
{
var openAsync = conn.Open();
if (waitForOpen) conn.Wait(openAsync);
}
return conn;
}
RedisConnection 对象的通用扩展方法:
public static T Get<T>(this RedisConnection conn, string key, int dbNum = 0)
{
if (typeof (T) == typeof (byte[]))
{
var task = conn.Strings.Get(dbNum, key);
var result = conn.Wait(task);
return (T) (object) result;
}
else
{
var task = conn.Strings.GetString(dbNum, key);
var result = conn.Wait(task);
if (result == null || typeof(T) == typeof(string))
return (T)(object)result;
return JsonSerializer.DeserializeFromString<T>(result);
}
}
public static void Set<T>(this RedisConnection conn, string key, T value, int dbNum = 0)
{
if (typeof (T) == typeof (byte[]))
{
conn.Strings.Set(dbNum, key, value as byte[]);
return;
}
var serializedValue = JsonSerializer.SerializeToString(value);
conn.Strings.Set(dbNum, key, serializedValue);
}