jjzjj

c# - 服务栈.Redis : PooledRedisClientManager creating way too many connections

coder 2023-07-18 原文

我想我在这里做错了什么。在我开始之前,先了解一下背景。

我们公司使用一种名为 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 网络服务进行了一些测试,模拟了 50 个左右的用户。这是我们目前的发现:

  • 该问题只发生在 IIS ASP.NET 应用程序内部。在具有高并发性的控制台应用程序上对其进行测试无法重现该问题。
  • 池本身只被创建一次。整个应用程序共享这个单一实例。
  • 在上面的 GeneXus 示例中,完全证明了在从 &RedisClient.Check()&RedisClient.Close() 的调用中使用了单个连接。
  • 但是 当调用另一个 &RedisClient.Check() 时,通常会创建另一个连接(显然它不会重用之前关闭的客户端),我们最终在 Close Wait 状态下有成千上万(假设池限制为 5000)的 TCP 连接(这有点大),这些连接不会被重用。
  • 当它达到池限制时,我们有一些处理逻辑(我没有放在这里)在池超时后使用 new RedisClient() 创建一个新连接,这可能是认为这不是处理该问题的最明智的方法,但是......它会这样做一段时间,然后所有处于 Close Wait 状态的数千个连接开始关闭,然后池开始再次工作。

我的问题是:为什么它不重用 TCP 连接?它在控制台应用程序模拟中运行良好,但当我们使用 IIS 将其用于我们的 Genexus 应用程序时,它只会不断创建这些连接。

是我一直弄错了这个游泳池,还是我做错了什么?

注意:目前我提供了所有这些信息,但如果您需要更多,没问题。我只是不知道还能提供什么。

编辑:已解决。我的代码试图变得过于聪明。我把它简化了,现在它可以正常工作了,尽管我仍然不明白我做错了什么。此外,我假设绝对所有与 Redis 的连接在使用后立即关闭,结果证明是错误的。

最佳答案

访问客户端的典型使用模式是使用 using 语句,即:

using (var redis = redisManager.GetClient())
{
    //...
}

调用 Dispose() 将客户端释放回池中。

连接池统计

您可以通过打印 GetStats() 返回的字典来查看连接池内部统计信息的快照:

redisManager.GetStats().PrintDump();

Redis Stats

您还可以使用全局查看所有 Redis 客户端事件的总体统计信息:

RedisStats.ToDictionary().PrintDump();

我还会考虑减少您的连接池大小,因为 5000 的连接池接近于没有连接池。我的目标是让您的活跃连接数达到 ~2-3 倍。

关于c# - 服务栈.Redis : PooledRedisClientManager creating way too many connections,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33764374/

有关c# - 服务栈.Redis : PooledRedisClientManager creating way too many connections的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  8. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  9. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  10. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

随机推荐