我在使用BookSleeve连接和从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);
}
答案 0 :(得分:1)
Marc对这个问题的评论让我重新考虑如何利用关系。我在另一个问题上遇到了这个答案:
Maintaining an open Redis connection using BookSleeve
我最终使用上面链接的答案中的代码,删除了我发布的'GetUnsecuredConnection'方法,现在只需在构造/执行Redis操作之前检索打开的连接。
不再有SocketException,一切似乎都按预期运行。谢谢你提示Marc!感谢@ ofer-zelig提供的连接代码。
public Cache.CacheEntry Get(string key, bool updateAccessed)
{
var cacheKey = GetCacheableKey(key);
var conn = RedisConnectionGateway.Current.GetConnection();
var entry = conn.Get<Cache.CacheEntry>(cacheKey);
return entry;
}
public override void Add(string key, Cache.CacheEntry entry)
{
var cacheKey = GetCacheableKey(key);
var conn = RedisConnectionGateway.Current.GetConnection();
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();
}
}