1.在Redis服务端设置了timeout后 利用ServiceStack.Redis类库set的时候就会报错Unable to read data from the transport connection: 远程主机强迫关闭了一个现有的连接。. 本地单机测试是不会出这个异常的,只有放到线上会出。。。
2.如果 不在redis服务端设置timeout的话 不会出现这个异常,但是redis客户端连接数闲置的连接会越来越多,而且闲置时间很长,随时间推移连接数达到了最大客户端连接数导致后面的客户端都无法连接redis了。。。
下面是代码:
public class RedisManager
{
/// <summary>
/// redis配置文件信息
/// </summary>
///
private static string RedisWritePath = System.Configuration.ConfigurationSettings.AppSettings["RedisWritePath"];
private static string RedisReadPath = System.Configuration.ConfigurationSettings.AppSettings["RedisReadPath"];
private static string RedisPassword = System.Configuration.ConfigurationSettings.AppSettings["RedisPassword"];
private static PooledRedisClientManager _prcm;
/// <summary>
/// 静态构造方法,初始化链接池管理对象
/// </summary>
static RedisManager()
{
CreateManager();
}
/// <summary>
/// 创建链接池管理对象
/// </summary>
private static void CreateManager()
{
_prcm = CreateManager(new string[] { RedisWritePath }, new string[] { RedisReadPath });
}
private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
{
//WriteServerList:可写的Redis链接地址。
//ReadServerList:可读的Redis链接地址。
//MaxWritePoolSize:最大写链接数。
//MaxReadPoolSize:最大读链接数。
//AutoStart:自动重启。
//LocalCacheTime:本地缓存到期时间,单位:秒。
//RecordeLog:是否记录日志,该设置仅用于排查redis运行时出现的问题,如redis工作正常,请关闭该项。
//RedisConfigInfo类是记录redis连接信息,此信息和配置文件中的RedisConfig相呼应
// 支持读写分离,均衡负载
return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
{
MaxWritePoolSize = 1600, // “写”链接池链接数
MaxReadPoolSize = 1600, // “读”链接池链接数
AutoStart = true,
});
}
private static IEnumerable<string> SplitString(string strSource, string split)
{
return strSource.Split(split.ToArray());
}
/// <summary>
/// 客户端缓存操作对象
/// </summary>
public static IRedisClient GetClient()
{
if (_prcm == null)
{
CreateManager();
}
//CreateManager();
IRedisClient redis = _prcm.GetClient();
redis.Password = RedisPassword;
return redis;
}
}
public abstract class RedisOperatorBase : IDisposable
{
protected IRedisClient Redis { get; set; }
//private bool _disposed = false;
protected RedisOperatorBase()
{
Redis = RedisManager.GetClient();
}
protected virtual void Dispose(bool disposing)
{
//if (!this._disposed)
//{
if (disposing)
{
Redis.Dispose();
Redis = null;
}
//}
//this._disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 保存数据DB文件到硬盘
/// </summary>
public void Save()
{
Redis.Save();
}
/// <summary>
/// 异步保存数据DB文件到硬盘
/// </summary>
public void SaveAsync()
{
Redis.SaveAsync();
}
}
public class RedisOperation: RedisOperatorBase
{
public WapPayLogBLL logBLL { get; private set; }
public bool Results { get; private set; }
public byte[] infos { get; private set; }
public ObjectSerializer ser { get; private set; }
public object obResults { get; private set; }
public RedisOperation()
{
logBLL = new WapPayLogBLL();
ser = new ObjectSerializer();
Results = false;
infos = null;
obResults = null;
}
#region RedisSetbyte
public bool Set(string key, object ob, DateTime ExpiresAt, string ErrLogName)
{
if (ob == null)
{
return Results;
}
try
{
if (Redis == null)
{
Redis = RedisManager.GetClient();
}
Results = Redis.Set<byte[]>(key, ser.Serialize(ob), ExpiresAt);
}
catch (Exception ex)
{
//在这里抛出了异常 Unable to read data from the transport connection: 远程主机强迫关闭了一个现有的连接。.
logBLL.Add(0, ErrLogName, "redis缓存存储失败", ex.Message, "", "");
}
finally
{
//释放内存
Dispose();
}
return Results;
}
}
调用:
web页面有一个页面多次用到了redis。
调用代码:
RedisOperation Redis = new RedisOperation();
HotelProxy proxy = new HotelProxy();
string key = "H5_HotelPartMsg_" + hotelId;
proxy = Redis.Get(key, "H5_HotelPartMsg") as HotelProxy;
if (proxy != null)
{
return proxy;
}
//上面redis没有get到,下面读取数据库然后在set到redis
//这里是读取数据库的代码
......................
//读取数据库end
Redis.Set(key, proxy, DateTime.Now.AddMinutes(30), "H5_HotelPartMsg");
return proxy;
求大神帮忙看一下问题出在哪里,,困扰了好久
7 个解决方案
#1
顶一下。。。
#2
真的没有解决办法了么
#3
已解决。。。。
#4
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
#5
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
#6
猜测可能的原因是出在了链接池管理对象上 ,上面代码里是静态创建的,这样子整个项目都使用一个对象,然后从连接池取连接,我上面在redis服务端设置了timeout 闲置超时时间, 然后闲置的链接到超时时间了,服务端会把这个连接关掉,此时如果客户端正好有人在用这个程序,然后程序里使用了redis,这时候redis去链接池管理对象拿一个链接, 结果这个链接正好被服务端回收关闭了,那就会出现上面的错误、、、
解决办法把创建链接池管理对象相关的方法都改成非静态的 ,每次使用redis都重新创建连接对象 这样子就没问题了
#7
谢谢了,我参考一下
#1
顶一下。。。
#2
真的没有解决办法了么
#3
已解决。。。。
#4
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
#5
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
#6
猜测可能的原因是出在了链接池管理对象上 ,上面代码里是静态创建的,这样子整个项目都使用一个对象,然后从连接池取连接,我上面在redis服务端设置了timeout 闲置超时时间, 然后闲置的链接到超时时间了,服务端会把这个连接关掉,此时如果客户端正好有人在用这个程序,然后程序里使用了redis,这时候redis去链接池管理对象拿一个链接, 结果这个链接正好被服务端回收关闭了,那就会出现上面的错误、、、
解决办法把创建链接池管理对象相关的方法都改成非静态的 ,每次使用redis都重新创建连接对象 这样子就没问题了
#7
谢谢了,我参考一下