享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Distributed Application --- Start with Database Connection Pool

Posted on 2006-08-31 23:27  idior  阅读(14750)  评论(17编辑  收藏  举报

本文将主要介绍一个东西---Database Connection Pool(数据库连接池),虽然只是讲这么一个东西,但是通过它却能引出分布式应用的一个重要来由---为什么要分布?了解了Connection Pool,了解为什么要分布,这篇文章的目的就达到了。介绍开始: 

我们设计了一个C/S的应用,并且运用了逻辑分层的技术将代码分成了UIL-BLL-DAL,呵呵很酷不是,那当然我们面向对象,设计模式学的那是相当好。系统设计图大概就是下面这个样子:

 

       CS1 

 

这里的Server很简单就是一个SQL数据库服务器,每个Client通过连接它,读写数据完成各自的应用。这也是在80-90年代最经典C/S 2 Tiers分布式应用。其实那时候甚至没有BLL,界面加数据RAD的时代,也就在那时VB,Dephi流行起来。这样的结构算它分布式都有点勉强,Server端就是存储数据而已,基本上没有任何的业务逻辑,高级点的用上存储过程,算是把业务逻辑分布了,这也是为啥那段时间存储过程大行其道的一个原因吧。

通过这张图,很快就可以发现一个严重问题,现在只有三个Client, 如果有几十个,几百个甚至几千个Client同时连接数据库怎么办?要知道MSDE也是只支持5个并发连接的,难道MSDE,只能支持5个用户? 显然不会这样,因为5个用户不一定会在同一时间连接数据库啊,假设有A,B,C,D,E,F六个用户,A用户不读写数据库的时候,关闭连接,这样F用户不就可以用了,所以遵循良好的编程习惯(学习Dispose模式去),养成随手关门的好习惯。就可以充分利用这5个连接来服务十几二十个用户。

 

   1         using(SqlConnection conn=new SqlConnection(connStr))

   2         {

   3             conn.Open();

   4             //Read Write DB

   5         }

 

打开,操作,关闭,很简单嘛,这样就解决问题了吗?在这看似简单的过程中,你知道数据库同志有多难吗?连接数据库不仅要开销一定的通讯和内存资源,还必须完成用户验证、安全上下文配置任务。建立数据库连接的操作绝对可以算是系统中代价最大的操作之一。那怎么办?分布式正式登场。。。当当当当!

把DAL分布到Server端,并利用连接池就可以很好的解决以上的问题,如下图所示:

         CS2

为什么这样就解决问题了呢?我们知道数据库连接是有限的资源,有n个连接,那么在同一时间我们最多支持n个用户同时访问数据库。这点是不会变的。但是在现实情况下,n个用户不太可能同时访问数据库,所以n的连接往往可以支持2n,3n,甚至10n个用户。而达到这一目标的前提就是用户使用完连接后必须立即释放它,以让其他用户使用。但是如前所述,建立连接的代价非常高,如果由Client频繁建立关闭连接服务器,又会给Server带来巨大的负担。那么最好的方法就是希望连接能够重用,即Client A建立的连接不再关闭而可以直接被Client F使用。在数据库连接分别归各用户所有的时候(未使用分布式,DAL处于Client Domain的时候),当然无法实现连接的重用。而当DAL处于Server Domain的时候,复用就成了一件非常简单的事情。建立一个连接池,需要用的时候从中取出一个,不用的时候放回去,这样大家就充分利用有限的连接,服务于n倍的客户。而且此时也无须频繁的打开关闭连接,服务器就舒服多了。

   
Story在Roger Sessions 的 <<COM and DCOM>>一书中对连接池技术有一个非常形象的隐喻。

使用Taxi将乘客从市中心送到飞机场。
方法一: 每个乘客一辆车,很快飞机场的停车场及路上将堵满了车。
方法二: 每个乘客一辆车,车到了飞机场,就把车销毁。只要你的汽车公司的生产速度跟的上乘客的增加速度,并且你够有钱,那也没问题。
方法三: 每个乘客一辆车,车到了飞机场,就调头回去接其他的乘客。


Q: 所有连接都用一个连接池吗?

A: 根据连接字符串的不同,连接被分别存放在不同的池当中。

Q: 如果在Client Domain使用连接池会有什么样的效果?

A: 这样使用不仅没有好处,反而有坏处。这个答案看上去有点惊人,但是在了解了连接池的工作原理后,其实不难理解。连接池放在Server Domain的时候,可以被各个Client重复使用,而在Client Domain的时候,就无法被其他的Client复用了,此时使用它得不到任何好处。而且当连接被放入池中的时候,连接并没有被关闭,也就意味着即便该Client并不读写数据库,它也占用了一个有限的连接。

    这个问题在.Net下尤其需要引起注意,SqlConnection是默认使用连接池的,如果你的DAL是部署在Client端时,你应该尽可能的禁用连接池。在连接字符串中加入Pooling=False; 当然MS不会犯这么致命的错误。在你没有显式设置Pool的大小,或者Pool的Min为0时,当你将连接放入池中后,如果几秒中内没有再使用它的话,系统将自动关闭该连接,所以问题不是太大。

Q: 如何查看有关数据库连接的情况?

A: 控制面板->管理工具性能->性能   在图上点击右键添加计数器 选择数据库连接

  Cropper Capture[4] 
     Cropper Capture[3] 

本文介绍的内容非常基础,不过从中你可以了解到我们为什么要将DAL分布,从而开始了分布式的演化。

参考资料:
Microsoft .Net Distributed Application
Expert One-on-One J2EE Design and Develop
Pattern Oriented Software Architecture-Patterns for Resource Management 

相关资料:
Applying Distributed Application in .Net系列文章

---
后记:

之所以写这篇文章,其一网上很少有介绍(尤其中文),其二为之后介绍其他内容的时候提供引用连接。如有介绍不对的地方请指正。
本随笔完全使用Windows Live Writer写成,为我节约了大量时间(主要是排版问题),在此强烈推荐。