求助大神 ServiceStack.Redis出现异常(远程主机强迫关闭了一个现有的连接。)的问题

cxhgg 2017-03-30 10:18:21
问题描述:
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;



求大神帮忙看一下问题出在哪里,,困扰了好久
...全文
3163 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
一米阳光zw 2019-08-08
  • 打赏
  • 举报
回复
引用 8 楼 周大猫 的回复:
既然是连接池,想必一直保留在内存中,需要的时候从池中拿,怎么能每次使用redis都重新创建连接对象呢,那还要连接池干嘛。 另外连接池应该有自己的一套心跳机制,不会让redis服务端这么简单就回收。 例如连接池new 100个连接,几个小时内都没取,redis服务端全部回收了,那下次用时肯定报错,这样连接池不是鸡肋。 以上仅个人意见,准备查看redis源代码证实。
大神你验证的怎么样了,能跟大家分享一下吗
一米阳光zw 2019-08-08
  • 打赏
  • 举报
回复
引用 6 楼 cxhgg 的回复:
[quote=引用 5 楼 weixin_39313799 的回复:] 你好,我碰到同样的问题,这个问题怎么解决的,谢谢
猜测可能的原因是出在了链接池管理对象上 ,上面代码里是静态创建的,这样子整个项目都使用一个对象,然后从连接池取连接,我上面在redis服务端设置了timeout 闲置超时时间, 然后闲置的链接到超时时间了,服务端会把这个连接关掉,此时如果客户端正好有人在用这个程序,然后程序里使用了redis,这时候redis去链接池管理对象拿一个链接, 结果这个链接正好被服务端回收关闭了,那就会出现上面的错误、、、 解决办法把创建链接池管理对象相关的方法都改成非静态的 ,每次使用redis都重新创建连接对象 这样子就没问题了[/quote] 一般连接对象向连接池中归还连接时看起来我们调用的是close()方法,实际内部都不会真正的close,而是让连接池维护,至于何时关闭就跟连接池的参数有关系,可能是达到一定连接数量或许是其他时候
一米阳光zw 2019-08-08
  • 打赏
  • 举报
回复
引用 8 楼 周大猫 的回复:
既然是连接池,想必一直保留在内存中,需要的时候从池中拿,怎么能每次使用redis都重新创建连接对象呢,那还要连接池干嘛。 另外连接池应该有自己的一套心跳机制,不会让redis服务端这么简单就回收。 例如连接池new 100个连接,几个小时内都没取,redis服务端全部回收了,那下次用时肯定报错,这样连接池不是鸡肋。 以上仅个人意见,准备查看redis源代码证实。
说的很有道理,连接池很大一方面作用就是为了减少频繁创建和关闭连接带来的系统开销,项目并发到一定数量Redis就会炸掉,因为连接数太多
一个武术猴子 2019-07-19
  • 打赏
  • 举报
回复
引用 4 楼 cxhgg 的回复:
[quote=引用 5 楼 weixin_39313799 的回复:] 你好,我碰到同样的问题,这个问题怎么解决的,谢谢
猜测可能的原因是出在了链接池管理对象上 ,上面代码里是静态创建的,这样子整个项目都使用一个对象,然后从连接池取连接,我上面在redis服务端设置了timeout 闲置超时时间, 然后闲置的链接到超时时间了,服务端会把这个连接关掉,此时如果客户端正好有人在用这个程序,然后程序里使用了redis,这时候redis去链接池管理对象拿一个链接, 结果这个链接正好被服务端回收关闭了,那就会出现上面的错误、、、 解决办法把创建链接池管理对象相关的方法都改成非静态的 ,每次使用redis都重新创建连接对象 这样子就没问题了[/quote] 厉害厉害了学到了
周大猫 2018-08-02
  • 打赏
  • 举报
回复
既然是连接池,想必一直保留在内存中,需要的时候从池中拿,怎么能每次使用redis都重新创建连接对象呢,那还要连接池干嘛。
另外连接池应该有自己的一套心跳机制,不会让redis服务端这么简单就回收。
例如连接池new 100个连接,几个小时内都没取,redis服务端全部回收了,那下次用时肯定报错,这样连接池不是鸡肋。
以上仅个人意见,准备查看redis源代码证实。
weixin_39313799 2017-06-27
  • 打赏
  • 举报
回复
谢谢了,我参考一下
cxhgg 2017-06-26
  • 打赏
  • 举报
回复
引用 5 楼 weixin_39313799 的回复:
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
猜测可能的原因是出在了链接池管理对象上 ,上面代码里是静态创建的,这样子整个项目都使用一个对象,然后从连接池取连接,我上面在redis服务端设置了timeout 闲置超时时间, 然后闲置的链接到超时时间了,服务端会把这个连接关掉,此时如果客户端正好有人在用这个程序,然后程序里使用了redis,这时候redis去链接池管理对象拿一个链接, 结果这个链接正好被服务端回收关闭了,那就会出现上面的错误、、、 解决办法把创建链接池管理对象相关的方法都改成非静态的 ,每次使用redis都重新创建连接对象 这样子就没问题了
weixin_39313799 2017-06-26
  • 打赏
  • 举报
回复
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
weixin_38210368 2017-04-08
  • 打赏
  • 举报
回复
你好,我碰到同样的问题,这个问题怎么解决的,谢谢
cxhgg 2017-03-31
  • 打赏
  • 举报
回复
已解决。。。。
cxhgg 2017-03-31
  • 打赏
  • 举报
回复
真的没有解决办法了么
cxhgg 2017-03-30
  • 打赏
  • 举报
回复
顶一下。。。

111,094

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧