是否有在.net中实现专有连接池的标准方法?

时间:2009-07-18 20:15:23

标签: c# .net api pooling

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

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

3 个答案:

答案 0 :(得分:6)

  

是否存在标准连接池模型

除了ADO.NET,没有。但是ADO.NET模型很简单。构造一个对象以从池中获取连接,或者重新创建一个对象,并在Close / Dispose / Finalize上将其返回到池中。

从这个可以立即确定一个实现模式:

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

实施中有一个选择。当一个对象被分发时,池是否还需要保留引用?如果它确实需要跟踪哪些对象是活动的以及哪些对象是合并的;否则可以使用简单的可用对象集合。

类似的东西:

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 (totalOjects >= 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 imp

}

这不适合MyObject被摧毁的情况。例如。保存对已分配的MyObject的弱引用的集合,如果池为空,则检查已处置的实例。如果您不能依赖客户端来关闭或处理实例,或者在MyObjectImpl 1 上实现终结器(并在调试版本中将其报告为错误),那么也需要这样做。

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

答案 1 :(得分:4)

更新

实际上现在我知道更多,我想我会使用我选择的IoC container中的一项功能 - Castle Windsor。其中一个内置的lifestyles是“pooled”,这意味着每当你向容器询问一个以这种生活方式注册的对象时,它会给你一个合并的对象,如果它可以,或者创​​建一个新的。

此前...

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

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


对于数据库连接:

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

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

答案 2 :(得分:0)

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