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

发布于 2024-07-27 04:23:32 字数 247 浏览 11 评论 0原文

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

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

Is there a standard connection pooling model (or API) similar to that used by the data providers in .net that I could use to implement my own connection pool?

I ask because I have a requirement to implement my own connection pool to a proprietary TCP/IP device that we use in a web service. The current problem is that there are lot of connections (read too many) to the device due to the threaded nature of web services running under IIS. I want to limit the number of these connections using my own connection pool and it seems stupid to reinvent the wheel if there is a standard model I could use to do this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

缱倦旧时光 2024-08-03 04:23:33

是否有标准的连接池模型

除了 ADO.NET 之外, ,没有。 但 ADO.NET 模型非常简单。 构造一个对象以从池中获取连接,或重新创建一个对象,并在 Close/Dispose/Finalise 时将其返回到池中。

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

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

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

类似于:

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

Is there a standard connection pooling model

Other than ADO.NET, no. But the ADO.NET model is nice an simple. Construct an object to get a connection from the pool, or created anew, and it is returned to the pool on Close/Dispose/Finalise.

From this one can immediately determine an implementation pattern:

  • The client type is a proxy to the real type, and has a lifetime from creation to
    Close/…. It is a proxy to the real object. Provides methods and properties which
    forward to the real connection.
  • The real connection is a long lived instance, created by the pool, given out under a proxy
    and then returned at the end of the proxy.

There is a choice in the implementation. When an object has been handed out, does the pool need to also keep a reference? If it does the pool needs to track which objects are active and which are pooled; otherwise a simple collection of available objects can be used.

Something like:

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

}

This doesn't cater for instances of MyObject being destroyed. E.g. hold a collection of weak references to allocated MyObject's, and if the pool is empty check for disposed instances. This would also be needed if you cannot rely on client's to Close or dispose of instances, or implement a finaliser on MyObjectImpl1 (and report this as an error in debug builds).

1 This cannot be done on MyObject because by the time MyObject was finalised the MyObjectImpl instance could already have been finalised.

梦与时光遇 2024-08-03 04:23:33

更新

实际上现在我知道更多了,我想我会使用我的 IoC 容器 选择 - 温莎城堡。 内置生活方式之一是“pooled",这意味着每当您向容器请求使用此生活方式注册的对象时,它都会给出如果可以的话,您可以选择池对象之一,否则创建一个新对象。

以前......

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

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


对于数据库连接:

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

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

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.

黑色毁心梦 2024-08-03 04:23:33

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

Web service methods are meant to be stateless (i.e. no objects are maintained in existence on the server between calls). What you want to do is maintain a collection of proprietary connection objects on the server between calls, and allocate existing connection objects from this pool to each method call (instead of creating a new connection object in each method).

A simple way to do this is to declare your collection of objects as "private static" within the scope of your web service but outside the scope of any method, like this:

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

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

and then populate the collection from the web service's startup event (I don't remember what event that is at the moment - I'll be back with it in a second). Any method that needs to use a connection would get a connection object from this list, instead of creating a new one (you'll have to handle the method of allocating connections and marking them as "in use" and so on).

This will work fine if your web service is called frequently (web services usually shut down after 20 minutes of inactivity, which would necessitate rebuilding the connection pool for the next call). If you need to maintain your collection of connections beyond that, check out this article:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文