加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

.NET 连接池

发布时间:2020-12-12 15:48:06 所属栏目:MsSql教程 来源:网络整理
导读:? 防止可淹没应用程序的池溢出 William?Vaughn 大多数?ADO.NET?数据提供程序使用连接池,以提高围绕?Microsoft?断开连接的?.NET?结构构建的应用程序的性能。应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个查询,然后处理行集
防止可淹没应用程序的池溢出 William?Vaughn 大多数?ADO.NET?数据提供程序使用连接池,以提高围绕?Microsoft?断开连接的?.NET?结构构建的应用程序的性能。应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个查询,然后处理行集,最后将连接释放回连接池。如果没有连接池,这些应用程序将花费许多额外时间来打开和关闭连接。 当您使用?ADO.NET?连接池来管理基于?Web?的应用程序和客户端/服务器?Web?服务应用程序的连接时,您的客户通常会获得更快的连接和更好的总体性能。但是,当您的应用程序或?Web?站点上突然涌入了同时希望进行连接的大量客户时,会发生什么事情呢?您的应用程序会“沉没”,还是会“游泳”?就像救生员一样,您需要仔细监视连接池,以维护它的良好性能,并防止连接池发生溢出。我们首先探讨连接池可能溢出的原因,然后讨论如何编写代码或使用?Windows?性能监视器来监视连接池。 正如我于?2003?年?5?月发表的?"Swimming?in?the?.NET?Connection?Pool"?(InstantDoc?ID?38356)?一文中讨论的那样,当您使用连接池时,您需要知道许多有关可伸缩性和性能的详细信息。请记住,您需要监视和管理两个基本因素:每个池管理的连接数和连接池的数量。在一个有效的生产系统中,池的数量通常很少(1?到?10),而且,使用中的连接的总数也很少(少于?12?)有效的查询只用不到一秒钟的时间就可以完成,并断开连接。因此,即使有数百个客户同时访问您的?Web?站点,相对较少的几个连接常常足以处理整个负载。为了使您的应用程序有效地运行,您必须使连接资源处于自己的控制之下,并要监视池的状态,这样,在监视池发生溢出以及您的客户开始抱怨(或离开您的网站)之前您会收到某种警告。 为什么会发生连接池溢出? 参加电子邮件讨论组的人常常抱怨应用程序是如何在测试中是“龙”而在形成为产品时就变成了“虫”的。有时,他们会报告说,当连接了大约?100?个客户端时,应用程序会停止或挂起。请记住,一个池中的默认连接数是?100。如果您尝试从池中打开?100?个以上的连接,ADO.NET?会使应用程序的连接请求排队等候,直到有空闲的连接。应用程序(及其用户)将这种情况视为进入?Web?页的延迟或视为应用程序死锁。让我们首先讨论一下这个问题是如何产生的。 在?ADO.NET?中,SqlClient?.NET?数据提供程序为您提供了两种打开和管理连接的方法。首先,当您需要手工管理连接时,可以使用?DataReader?对象。利用这种方法,您的代码将构造一个?SqlConnection?对象,设置?ConnectionString?属性,然后使用?Open?方法来打开连接。当代码完成?DataReader?后,您要在?SqlConnection?对象停止作用之前关闭?SqlConnection。要处理行集,您可以将?DataReader?传递到应用程序中的另一个例程,但仍然需要确保?DataReader?及其连接处于关闭状态。如果您不关闭?SqlConnection,代码会“泄漏”每个操作的连接,于是连接池对连接进行累积,最后便发生溢出。与?ADO?和?Visual?Basic?(VB)?6.0?中的情况不同,.NET?垃圾回收器不会为您关闭?SqlConnection?并进行清理。我稍后要讨论的?清单?1?显示了如何打开连接和生成?DataReader?以从一个简单的查询返回行集,来向连接池施加压力的。 您也可能在使用?DataAdapter?对象时遇到问题。DataAdapter?Fill?和?Update?方法可自动打开?DataAdapter?对象的连接,并在数据?I/O?操作完成后关闭该连接。不过,如果该连接在执行?Fill?或?Update?方法时已经处于打开状态,那么,ADO.NET?在方法执行完以后不会关闭?SqlConnection。这是另一个发生连接“泄漏”的机会。 此外,您还可以使用基于?COM?的?ADO?从?.NET?应用程序创建连接。ADO?利用与?ADO.NET?相同的方式将这些连接组合成池,但不能像您使用?SqlClient?ADO.NET?数据提供程序时那样,提供从应用程序监视连接池的方式。 指示?DataReader 孤立连接和溢出池是严重的问题,根据有关这些问题的新闻组讨论的数量来看,它们十分常见。这些问题最有可能是由?DataReader?引起的。为了测试?DataReader?的行为,我编写了一个?Windows?窗体?(WinForms)?示例应用程序,该示例突出了?CommandBehavior.CloseConnection?选项。(您可以在? 现在您必须决定要采取的措施,我不建议您告诉用户您已经用完了所有连接。有些应用程序会通知用户系统正忙于帮助其他客户,并建议用户稍后进行访问。其他应用程序则播放一段动画,通知用户系统尚未死锁,而是正在忙于处理他们的请求。同时,您的代码重新尝试操作。在所有情况下,您应该记录这些故障,以便帮助诊断问题的症结所在,并记录您已经耗尽了资源。 监视连接池 您已经打开和关闭了一个连接,现在您希望知道该连接是否仍然处于打开状态。您可以使用几种方法来确定有多少连接仍然处于打开状态,以及它们正在执行何种操作: ????? 运行?sp_who?或?sp_who2。这些系统存储过程从?sysprocess?系统表返回信息,该系统表显示所有工作进程的状态及其有关信息。通常,您会看到每个连接有一个服务器进程?ID?(SPID)。如果您是通过在连接字符串中使用?Application?Name?参数来命名您的连接的,那么,您将很容易找到工作的连接。 ????? 使用带有?SQLProfiler?TSQL_Replay?模板的?SQL?Server?事件探查器来跟踪打开的连接。如果您很熟悉事件探查器,此方法比通过使用?sp_who?进行轮询要更容易。 ????? 使用性能监视器来监视池和连接。我稍后再讨论此方法。 ????? 在代码中监视性能计数器。您可以通过使用例程来提取计数器或通过使用新的?.NET?PerformanceCounter?控件来监视连接池的状况和已建立的连接的数量。这两种方法都包括在您可以从? 您还可以通过使用?SQL?Server?性能计数器?"User?Connections"?来监视打开的连接的数量。该计数器被列在?Performance?对象下拉列表中的?SQL?Server:?General?Statistics?下。我喜欢监视?"User?Connections"?值和一些所选定的?.NET?CLR?Data?SqlClient?计数器(我稍后将讨论此内容),因为我可以获得我需要的信息,而不必担心实例。 使用代码来监视性能计数器。当您需要以编程方式监视连接池时,您可以编写代码来监视由?SqlClient?管理的性能计数器?—?这些计数器与?MMC?Windows?NT?性能监视器管理单元所提供的计数器是相同的。编写执行监视的代码似乎是一件有些令人畏惧的事情。但我已经提供了从?SqlClient?提供程序的内部工作提取这些计数器的例程的快照(作为本文提供的可下载程序之一)。 您可以编写检查?表?2显示的五个计数器的代码。通过利用这五个计数器,您可以实时监视连接池。.NET?预期您会在性能监视器中提供一个类别?—?复制的?Performance?Object?—?并从那些注册到系统的计数器中选择适当的计数器。要访问?SqlClient?计数器,请将该类别设置为?".NET?CLR?Data"。 使用?PerformanceCounter?控件。您可能会发现,在设计时向您的应用程序窗体添加?PerformanceCounter?要比手工编写代码来访问性能计数器更加容易。要使用?PerformanceCounter?控件,请从“Visual?Studio?.NET?工具箱组件”菜单中选择一个?PerformanceCounter,将它拖到您的应用程序窗体,然后设置属性,如?图?2?所示。这些控件工作在?Web?窗体和?WinForms?应用程序中。 因为?PerformanceCounter?控件提供了方便的下拉列表,所以,您可以在设计时看到任何一种性能计数器类别、计数器名称和特定实例?—?您将要运行的实例除外。这意味着您必须使用图?2?显示的方法来捕获应用程序正在使用的池的适当实例。为了回避这个问题,我选择?_global_?实例。再次说明一下,此方法假设某个应用程序已经至少创建了一个池,因此您需要做好不存在计数器实例时?ADO.NET?引发异常的准备,就像它在不存在池连接时也会引发异常一样。 注意不准确的池计数。因为?SqlClient?.NET?数据提供程序中存在?.NET?框架?1.1?尚未解决的错误,所以,性能计数器会在池实际上已经删除时错误地指示池“仍然存在”。我能通过结束?MMC?性能监视器管理单元、然后结束?Visual?Studio?.NET?来验证池已经不再存在。这些步骤说明,.NET?数据提供程序在创建连接池的进程结束时会正确地删除连接池。显然,这种不准确性降低了性能计数器在监视池方面的有效性,所以我希望?Microsoft?将来能解决这个问题。 计数器不显示的内容 您可能会面临的一个问题是无法从计数器或?SqlClient?属性看到每个池的配置。每个?SqlConnection?对象的?ConnectionString?保存着这些池设置的密钥。因为您不能依赖于默认设置,所以很难确定池几乎已满或很难使用。这会成为未来版本的?ADO.NET?的另一个方便功能。 不过,假设您知道各个连接池?ConnectionString?参数的值,则利用清单?1?中的代码,您可以很容易地设置一个计时器来检查您创建的特定池并报告使用百分比。然后,监视应用程序会向您发出警报,以便您可以解决问题并防止溢出。 最后,请记住,ADO.NET?采用的方法与基于?COM?的?ADO?有所不同。Visual?Basic?.NET?完全改变了放弃对象的方式,并且不再确保?Connection?对象在停止作用时被关闭。请确保?SqlConnection?对象(或任何?Connection?对象)在停止作用之前被关闭。 连接池是一种非常强大的功能,它可以提高应用程序的性能。但如果您不是一个出色的救生员,您的连接池会成为一个危害而不是一个优点。我希望本文讨论的方法有助于您有效地监视连接池并满足用户的需要。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

?
    推荐文章
      热点阅读