我有一个连接到远程数据库的 .net 客户端应用程序。在客户端的生命周期(小时)内保持单个连接打开是否安全?
如果我有多个(10 或 100 个)客户端运行,答案是否成立?
我有一个连接到远程数据库的 .net 客户端应用程序。在客户端的生命周期(小时)内保持单个连接打开是否安全?
如果我有多个(10 或 100 个)客户端运行,答案是否成立?
这样做绝对安全。这就是客户端-服务器应用程序的工作方式。如果您使用的是三层应用程序,则应用程序服务器将保持连接池处于打开状态。
可扩展性是一个问题,或者至少曾经是机器内存比现代套件少的时代。对于两层(客户端-服务器)应用程序,每个客户端都打开一个连接并保持打开状态。这有几个影响:
每个连接都使用内存,因此大量(相对)空闲连接会耗尽机器内存。但是,现代的 64 位服务器可以拥有数十或数百 GB 的内存,因此它可以支持非常大量的此类连接。
如果客户端计算机上未提交事务,则只要事务打开,锁就会保持打开状态。这导致了一类问题,当有人可以开始交易,去吃午饭并忘记他们留下了一些东西时。这将一次将事务引用的任何记录锁定几个小时。
然而,事务可以很容易地覆盖对数据库的多个访问,这对于连接池来说更难做到。
池化架构(在 3 层架构中很常见)在应用程序服务器和数据库之间具有有限数量的连接。查询只需使用下一个可用连接并立即提交更新。这使用更少的资源,因为您只打开了有限数量的连接,并且(结合乐观并发策略)将消除大量潜在的应用程序并发问题。
为了使用长事务(即覆盖对数据库的多次调用的事务),必须将事务与连接分离。这是 TP 监视器的基本架构,并且有一些标准协议(例如XA或OLE 事务)来支持这一点。如果这种类型的外部管理事务不可用,则应用程序必须构造一个补偿事务,以撤消应用程序事务所做的更改。工作流管理系统经常使用这种类型的架构。
根据业务操作打开和关闭您的连接
如果您正在谈论客户端/服务器应用程序,我建议您在使用完每个连接后立即关闭它。虽然每个单独的应用程序实例可能会在打开连接时对性能造成很小的影响,但您的应用程序作为一个整体将可以更好地扩展。这在一定程度上取决于您使用的数据库服务器。SQL Server 将根据安装的硬件处理不同数量的并发连接。如果您想将客户端/服务器应用程序扩展到数千个桌面,小型数据库服务器可能无法处理所有打开连接的桌面,但可以很好地处理仅打开部分连接的数千个桌面。
几年前我亲眼目睹了这一点。一个部署到几个部门的应用程序没有出现任何问题,然后在整个组织中部署。应用程序很快非常非常慢。该组织正在考虑为他们的数据库服务器购买一块非常昂贵的硬件来获得一些性能。我建议他们在每次业务操作后打开和关闭数据库连接。幸运的是,他们已经构建了应用程序,因此这不是一个困难的更改。他们在每周一次的网络更新中进行了更改并推出了它。一夜之间,应用程序性能显着提高。他们节省了数千美元。
长期联系的困难在于您可能无法完全确定它们是否仍然存在。网络故障、服务器重新启动或有状态防火墙忘记其某些状态都可能导致“陈旧”的连接看起来是打开的,但当您尝试使用它时会出现错误。
连接池方案通常通过让一些系统偶尔检查池中的连接是否健康,或者在超时之后丢弃未使用的连接来解决这个问题。
一般来说,在分布式系统中,您需要围绕各种故障进行编码,保持长期连接打开会使这变得更加困难 - 但如果您愿意这样做,那就太好了。
虽然具体细节通常很重要,但长时间保持连接打开并没有错。
如果您的应用程序是连接池 - 池中的连接槽通常保持连接,直到需要它们。
在基于连接的许可模型之外,现在非常罕见,维护连接本身消耗的资源可以忽略不计。
通过 TCP 运行的 SQLServer 客户端每隔 30 秒发送一次保活。(Keepalive 本质上是 0 len TCP 数据包)通常认为是可忽略的流量。
如果您在带宽非常少或 WLAN 链接不可靠的环境中运行,则增加 TCP 保持活动间隔可能有助于提高长时间连接保持活动状态的机会并减少线路上的“空闲聊天”数量。
您会或不想使用连接池是有原因的。
反对使用池:
消除环境污染的可能性 - 其他查询设置可能干扰查询执行的特殊环境选项(xact_abort,事务隔离级别..等)
如果配置/许可的连接限制有效,则应用程序中的空闲连接是其他应用程序无法使用的连接。
反对每次连接:
连接设置(尤其是安全连接设置)需要在客户端和服务器之间进行多次额外的往返——往返往往是 WAN 应用程序的性能杀手。
它确实取决于您拥有打开连接的客户端数量以及您是否使用任何类型的连接池。
如果您是三层系统并且您的中间层启用了连接池,则客户端设置不适用。如果您不使用中间层,那么如果您担心与服务器的连接数量,那么现在是考虑它的时候了,因为这个中间层将帮助您更好地管理它。
每个打开的连接都会占用服务器上一定数量的内存并增加一些开销。给定一个两层系统,其中客户端直接与服务器通信,那么您需要查看服务器的规格和客户端数量,看看是否值得保持连接打开。如果您是一个两层系统并且您有数千个活动客户端,那么您可能不想让它们全部打开......如果您是一个两层系统并且只有几十个客户端,那么让它们保持打开.
一般来说,您不应该像这样保持连接打开。.NET 有一个 ADO.NET 连接池系统,它完全可以满足您的要求,并且做得更好。;-)
更新:我是一个'tard。被动地发布。不适用于这里。
-Oisin
当然。当您长时间保持事务打开时(在某些隔离级别),您确实只会遇到问题。
有一个许可的连接限制,并且连接确实会占用服务器上的内存,所以越少越好。
这是安全的。这几乎就是池的作用......在程序运行期间保持连接打开并将其用于不同的查询。
但是您可能需要注意数据库连接超时。连接将失效,您将开始收到奇怪的错误。将数据库中的超时值设置为一个非常大的值,或者通过偶尔的虚拟查询保持连接。
取决于数据库以及您正在使用它做什么。大多数情况下,打开和关闭任何连接都会产生费用。例如,如果您在移动设备(SQL Server Compact Edition)上使用 SQLCE,那么实际上推荐的方法是在设备上保持连接打开,因为打开和关闭连接的费用不值得麻烦。
现在相比之下,如果您正在使用多用户数据库,您将需要更仔细地管理这些连接。如前所述,ADO.Net 连接池在帮助您管理效率方面做得很好。