5

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

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

4

3 回答 3

6

是否有标准的连接池模型

除了 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 实例可能已经完成。

于 2009-07-19T08:32:13.910 回答
4

Update

Actually now I know more, I think I'd use a feature from my IoC container of choice - Castle Windsor. One of the built-in lifestyles is "pooled", which means that whenever you ask the container for an object that was registered with this lifestyle, it'll give you one of the pooled objects if it can, or else create a new one.

Previously...

I think you want to implement "object pooling". Here's a few things that looked promising:

Of course with your pooled objects, you need to be careful with concurrency and thread synchronisation etc.


For database connections:

You can control the number of connections in the .NET connection pool with an option in the connection string: "max pool size" as described in: http://msdn.microsoft.com/en-us/library/8xx3tyca(VS.71).aspx

Try to avoid implementing your own if you can.

于 2009-07-18T20:29:27.500 回答
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

于 2009-07-18T21:55:15.343 回答