【发布时间】:2016-02-19 06:18:35
【问题描述】:
我想我在这里做错了什么。在我开始之前,先介绍一下上下文。
我们公司使用名为 GeneXus 的工具:它是代码生成器工具之一,已使用多年。它生成 C# 代码,因此我们可以构建自己的程序集并使其与该工具一起使用。我们的应用程序处理了很多 SOAP 调用,并且还很好地利用了 Redis。事实上,Redis 是整个代码基础设施的主要部分。
为了让它与 GeneXus 一起工作,我们必须围绕 ServiceStack.Redis 库创建一个包装类,以便可以在我们的 GeneXus 代码中使用它。这就是我们在 GeneXus 中使用它的方式:
//First we check if Redis is working at all. It just pings the Redis server.
If &RedisClient.Check()
//Here we make several calls to get and set some data. Like that:
If &RedisClient.Exists("Some_Key")
&MyData = &RedisClient.Get("Some_Key")
Else
&MyData = FetchFromSQLServerDatabase()
&RedisClient.Set("Some_Key", &MyData)
EndIf
//We are done with Redis, close it.
&RedisClient.Close()
EndIf
这是一个简单的例子,但我们的包装器一直是这样使用的:检查它是否在线,做几件事然后关闭客户端。
对.Close() 的调用在后台调用.Dispose() 方法。
这就是我们在包装器中管理客户端创建的方式。
首先,我们有一个 RedisProvider 类,它是一个单例。做一些测试,我们确保池只创建一次。我们在单例 RedisProvider 中创建一个像这样的池实例:
Pool = new PooledRedisClientManager(
poolSize: poolSize,
poolTimeOutSeconds: timeout,
readWriteHosts: hosts);
而且这个 RedisProvider 类也有这样的方法:
public RedisClient GetClient() => (RedisClient)Pool.GetClient();
我们目前的发现:
我们使用 Apache JMeter 对我们的 SOAP Web 服务进行了一些测试,模拟了大约 50 个用户。这是我们目前发现的:
- 该问题仅发生在 IIS ASP.NET 应用程序内部。在具有高并发性的控制台应用程序上对其进行测试无法重现该问题。
- 池本身只被创建一次。整个应用程序共享这个单一实例。
- 在上面的 GeneXus 示例中,完全证明了在从
&RedisClient.Check()到&RedisClient.Close()的调用中使用了单个连接。 -
但是当另一个
&RedisClient.Check()被调用时,通常会创建另一个连接(显然它不会重用之前关闭的客户端),我们最终会拥有数千个(假设池限制为 5000)处于Close Wait状态的 TCP 连接数(有点大),不会被重用。 - 当它达到池限制时,我们有一些处理逻辑(我没有放在这里)在池超时后使用
new RedisClient()创建一个新连接,人们可能认为这不是最聪明的处理方式那个,但是很好......它会这样做一段时间,然后所有处于Close Wait状态的数千个连接开始关闭,然后池再次开始工作。
我的问题是:为什么不重用 TCP 连接?它在控制台应用程序模拟中运行良好,但是当我们使用 IIS 将它用于我们的 Genexus 应用程序时,它只是不断创建这些连接。
我是不是一直把这个泳池的事情弄错了,还是我做错了什么?
注意:现在我提供所有这些信息,但如果您需要更多信息,没问题。我只是不知道还能提供什么。
编辑:已解决。我的代码试图太聪明。我把它弄糊涂了,现在它工作正常,虽然我仍然不明白我做错了什么。此外,我假设所有与 Redis 的连接在使用后都会立即关闭,但结果证明是错误的。
【问题讨论】:
-
4年后,你是怎么解决的?我现在遇到同样的问题...
-
你可以尝试使用 StackExchange.Redis 代替 @Ted
-
ServiceStack.Redis 没有任何反对意见,但 StackExchange 是免费和开源的。实际上我遇到了更糟糕的问题,但我认为这是由于我们当时奇怪的开发环境和技术堆栈。从那时起,asp.net core 发生了很大的变化。
-
无论什么工作 =) 我的情况是,如果我没记错的话,根据一些基准,StackExchanges lib 比 ServiceStack 慢得多。此外,StackExchange 缺少一些对我来说非常重要的功能。由于我正在使用 ServiceStacks 的其他库/API,因此我很自然地会继续使用它。 SS Redis 库现在对我来说运行良好,即使我时不时地有一些功能请求。 Mythz 非常快速地回答问题并添加功能(他同意)=)
-
出于好奇,这是我为 SE.Redis (github.com/StackExchange/StackExchange.Redis/issues/437) 打开的一个 github 问题。忽略那些令人毛骨悚然的写作:)你解决了你原来的问题吗?已经快一年了......与你所说的相反,我总是发现 SE.Redis 更快,可能是由于异步 I/O。我们用的免费版SS没有这个功能,现在肯定不一样了。
标签: c# iis redis servicestack