【问题标题】:Is there a standard way of implementing a proprietary connection pool in .net?是否有在.net 中实现专有连接池的标准方法?
【发布时间】:2009-07-18 20:15:22
【问题描述】:

是否有类似于 .net 中的数据提供者 使用的标准连接池模型(或 API),我可以使用它来实现我自己的连接池?

我问是因为我需要实现我自己的连接池到我们在 Web 服务中使用的专有 TCP/IP 设备。当前的问题是,由于在 IIS 下运行的 Web 服务的线程特性,设备有很多连接(读取太多)。我想使用我自己的连接池来限制这些连接的数量,如果有一个标准模型我可以用来做这件事,那么重新发明轮子似乎很愚蠢。

【问题讨论】:

  • 您使用哪些 .NET API 与设备通信?插座? TCPClient?
  • 我正在使用 TCPClient 类。

标签: c# .net api pooling


【解决方案1】:

是否有标准的连接池模型

除了 ADO.NET,没有。但是 ADO.NET 模型非常简单。构造一个对象从池中获取连接,或者重新创建,并在关闭/处置/完成时返回到池中。

由此可以立即确定一种实现模式:

  • 客户端类型是真实类型的代理,从创建到有生命周期 关闭/…。它是真实对象的代理。提供方法和属性 转发到真正的连接。
  • 真正的连接是一个长期存在的实例,由池创建,在代理下发出 然后在代理结束时返回。

在实现中有一个选择。当一个对象被分发出去后,池是否也需要保留一个引用?如果是,池需要跟踪哪些对象是活动的,哪些是池化的;否则可以使用可用对象的简单集合。

类似:

internal class MyObjectImpl {
  // The real object that holds the resource
}

internal static class MyObjectPool {
  private static object syncRoot = new object();
  private static Queue<MyObjectImpl> pool = new Queue<MyObject>();
  private static int totalObjects = 0;
  private readonly int maxObjects = 10;

  internal MyObjectImplGet() {
    lock (syncRoot) {
      if (pool.Count > 0) {
        return pool.Dequeue();
      }
      if (totalObjects >= maxObjects) {
        throw new PoolException("No objects available");
      }
      var o = new MyObjectImpl();
      totalObjects++;
      return o;
    }
  }

  internal void Return(MyObjectImpl obj) {
    lock (syncRoot) {
      pool.Enqueue(obj);
    }
  }
}

public class MyObject : IDisposable {
  private MyObjectImpl impl;

  public MyObject() {
    impl = MyObjectPool.Get();
  }

  public void Close() {
    Dispose();
  }

  public void Dispose() {
    MyIObjectPool.Return(impl);
    // Prevent continuing use, as the implementation object instance
    // could now be given out.
    impl = null;
  }

  // Forward API to implement

}

这不适用于MyObject 被破坏的情况。例如。持有对分配的MyObject 的弱引用的集合,如果池为空,请检查已处置的实例。如果您不能依赖客户端关闭或处置实例,或在 MyObjectImpl1 上实现终结器(并将其报告为调试构建中的错误),则也需要这样做。

1 这不能在 MyObject 上完成,因为当 MyObject 完成时,MyObjectImpl 实例可能已经完成。

【讨论】:

  • 一个非常有趣的想法,谢谢!如何让这个线程安全?
  • 显示的池是线程安全的。池化对象可能是线程安全的,也可能不是线程安全的,具体取决于其实现。我将更改MyObject.Dispose 以显式释放实现引用,这将避免在返回池后继续使用MyObject 实例。
  • 如果我想等待一段时间,直到一个池化对象可用,而不是立即抛出“没有可用的对象”异常,该怎么办?我将如何以线程安全的方式执行此操作?
【解决方案2】:

更新

实际上现在我知道的更多,我想我会使用我选择的IoC container 中的一个功能 - Castle Windsor。内置的lifestyles 之一是“pooled”,这意味着无论何时您向容器询问已使用此生活方式注册的对象,如果可以,它将为您提供池中的对象之一,否则创建一个新的。

以前...

我认为您想实现“对象池”。以下是一些看起来很有希望的事情:

当然,对于您的池对象,您需要小心并发和线程同步等。


对于数据库连接:

您可以使用连接字符串中的选项控制 .NET 连接池中的连接数:“最大池大小”,如:http://msdn.microsoft.com/en-us/library/8xx3tyca(VS.71).aspx 中所述

如果可以的话,尽量避免自己实现。

【讨论】:

  • 我无法使用任何标准的 .NET 连接池,因为我通过 TCP/IP(使用自定义协议)与专有设备通信,而不是与 MS/SQL 数据库的 Oracle。
  • 哦,我明白了。哈哈。所以基本上你想实现一个对象池,而不是一个连接池。我会更新我的答案...
【解决方案3】:

Web 服务方法是无状态的(即在调用之间服务器上不存在任何对象)。您要做的是在调用之间在服务器上维护一个专有连接对象的集合,并将该池中的现有连接对象分配给每个方法调用(而不是在每个方法中创建一个新的连接对象)。

一种简单的方法是将您的对象集合声明为在您的 Web 服务范围内但在任何方法范围之外的“私有静态”,如下所示:

public class Service1 : System.Web.Services.WebService
{
    private static List<CustomConnection> _connections = 
        new List<CustomConnection>();

    [WebMethod]
    public string HelloWorld()
    {
        return "Hello World";
    }
}

然后从 Web 服务的启动事件中填充集合(我不记得现在是什么事件 - 我会在一秒钟内回来)。任何需要使用连接的方法都会从这个列表中获取一个连接对象,而不是创建一个新的对象(你必须处理分配连接的方法并将它们标记为“正在使用”等等)。

如果您的 Web 服务被频繁调用,这将正常工作(Web 服务通常在 20 分钟不活动后关闭,这将需要为下一次调用重建连接池)。如果您需要维护您的连接集合,请查看这篇文章:

http://msdn.microsoft.com/en-us/library/system.web.httpapplicationstate.aspx

【讨论】:

  • 您可能想再次阅读他的问题。他没有使用 SOAP Web 服务。 -1.
  • 您可能想自己再阅读他的问题。我看到的只有“C#”、“.Net”、“IIS”和“Web 服务”。您在他的问题中看到了什么表明他没有使用像我的示例代码这样的网络服务?
  • 是的,它是一个标准的 .net 2.0 SOAP Web 服务。并感谢您的建议,但它已经(部分)以这种方式完成:连接是线程静态的。问题是这会导致大量连接:20 个 IIS 线程,每个线程有 5 个连接(到同一台机器上的不同 TCP/IP 端口),每个 Web 服务器有 100 个连接。使用 4 个 Web 服务器,这将导致与目标计算机的 400 个连接。
  • @VinceJS:然后查看我的答案中的 MSDN 链接。这将允许您在每个 Web 服务器上创建一次 5 个连接,然后每个对该服务器的请求都可以共享这些连接。它不处理服务器群,所以你仍然会有 20 个连接;我看不出如何在服务器之间共享连接池,除非您只有一台服务器直接连接到目标,而其他服务器都与第一台服务器通信。
  • 投赞成票是因为 OP 确认它实际上是一个 SOAP Web 服务,而 JS 投反对票是因为他认为它不是。
猜你喜欢
  • 2014-10-04
  • 2010-11-13
  • 2011-01-25
  • 2020-08-30
  • 1970-01-01
  • 2018-11-26
  • 2023-04-06
  • 2011-04-26
  • 2017-08-17
相关资源
最近更新 更多