我在一些.NET Web应用程序上工作,这些应用程序使用Redis进行大量缓存以及ServiceStack的Redis客户端。在所有情况下,我都在同一台机器上运行Redis。我已经使用了 BasicRedisClientManager 和 PooledRedisClientManager (总是以单例形式实现),并且两种方法都存在一些问题。
使用 BasicRedisClientManager ,事情会好一段时间,但最终Redis会开始拒绝连接。使用netstat,我们发现有数千个到默认Redis端口的TCP连接处于TIME_WAIT状态。
然后我们切换到 PooledRedisClientManager ,这似乎可以立即解决问题。但是,不久之后,我们开始注意到偶尔的CPU峰值,我们缩小到由PooledRedisClientManager.GetClient引起的线程等待(System.Threading.Monitor.Wait调用)。
在代码中,我们使用get-in-get-out方法(使用ServiceStack方便的ExecAs快捷方式),因此通常会非常频繁地获取连接,但会尽可能短暂地进行连接。
我们获得了适量的流量,但我们没有StackExchange,我不禁认为ServiceStack客户端能胜任工作,我们只是做错了。 PooledRedisClientManager是正确的方法吗?简单地增加池大小是否可取?或者这可能只是掩盖了我们代码的问题?
在这里寻找一般指导,我目前没有需要帮助的具体代码。提前谢谢。
答案 0 :(得分:5)
您是否绝对确定所有Redis连接都已被处置?
使用ServiceStack,Redis
和Service
上的ViewPageBase
属性(如果您使用的是SS Razor)会自行处理,但是只要您自己请求从池中连接,必须自己处理。
然而,尽管如此,我们最近还遇到了问题,我们的游泳池也因为所有连接而耗尽。我的一位同事发现没有正确清理Razor页面并发出拉取请求here - 这意味着自ServiceStack v4.0.21以来,Razor页面上只有正确的处理方式。我没有检查该修复程序是否已经反向移植到v3分支。
我的同事还添加了TrackingRedisClientsManager
,可以帮助您找到不当处置方式。见here
您还可以查看PooledRedisClientManager
by using this helper method的统计信息。我们把它扔在一个小剃刀页面上,以检查我们认为合适的统计数据)但你可以编写更好的代码来监控特定节点的池健康状况。