享受代码,享受人生

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.
posts - 98, comments - 2396, trackbacks - 162, articles - 45
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

本文将主要介绍一个东西---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写成,为我节约了大量时间(主要是排版问题),在此强烈推荐。

Feedback

#1楼  回复 引用 查看   

2006-09-01 08:42 by 浪子      
不错,很多初学者没有注意释放连接,导致数据库连接很快被填满了,特别是使用DataReader的时候,都没有设置连接行为,导致Reader一直抓着连接不释放。

P.S.
idior的写作风格也开始俏皮起来了。
live writer确实可以节省好多时间,强烈推荐!

#2楼  回复 引用 查看   

2006-09-01 09:15 by henry      
我觉得BL Layer应该放在AppService,以WS,Remotig的方式提供服务。这样Client Domain对业务逻辑依赖相对减少,业务逻辑的内部更改只需要更新AppService就可以,并不会给Client Domain带来更新上的麻烦。
BL Layer集中存放在管理上就更方便。

#3楼[楼主]  回复 引用 查看   

2006-09-01 10:24 by idior      
@henry
注意标题start with db connection,这仅仅是开始。

#4楼  回复 引用 查看   

2006-09-01 11:02 by 浪子      
@henry
BL Layer对象的序列化和反序列化怎么解决?
把BL全部放到WS还是有一定麻烦的,除非BL已经分析得非常通彻和稳定。

#5楼  回复 引用 查看   

2006-09-01 12:44 by henry      
@浪子
BL Layer处理输入的数据和提供输出的数据,搞不懂为什么要序列化?
WS其实就是作为数据输入和输出桥。

针对楼主描述的问题我的确犯了;不过我认为这情况无论在C/S 或B/S都存在。
因为Client Domain也可以是WebApplication

#6楼  回复 引用 查看   

2006-09-02 10:27 by 皇帝的新装      
BL Layer放在客户端是否合适?

#7楼  回复 引用 查看   

2006-09-03 16:07 by 老夫狂傲江湖      
自持,技術改變國運!

#8楼  回复 引用   

2006-09-05 14:58 by cc[匿名][未注册用户]
<<sql server 性能调校>

#9楼  回复 引用   

2006-10-12 00:10 by 川菜加盟网[未注册用户]
谢谢 提醒

#10楼  回复 引用 查看   

2006-11-09 15:38 by 我不是一只鹿      
今天来这又学了东西 呵呵 !idior大哥~`

#11楼[楼主]  回复 引用 查看   

2006-11-09 16:15 by idior      
@我不是一只鹿
不客气

#12楼  回复 引用 查看   

2006-12-01 10:17 by Kim Taehee      
分布式就仅仅只是这一个优点吗?就这一个使用它的原因吗?并且你的client端又是指的什么呢?是用户端,还是其它的服务器集群?
DataBase Connection楼主讲的没有错,我赞同,但是它仅仅是分布的一个引子,若扩大到涵盖为什么分布,不觉得不够吗?
我只能这么说对于这种和行业实际经验结合很紧的内容,和容易让人走错方向的内容,应该将文章类型摆正,是供大家参考(这点应该标明)和讨论!这样是对大家负责,也是对你自己负责。
此观点并不是针对谁,只是想大家有一个平台可以讨论问题!一起努力!

#13楼  回复 引用 查看   

2006-12-01 10:20 by Kim Taehee      
可能是没有看清楚楼主的题目,但是你的文章中可没有仅仅提到只是开始,并且你说得这个东东和我理解的分布式目的也不同!和微软专家提出的东东也不同!
专业研究,探讨.NET技术的群:12339353.本群是.NET开发人员的交流空间,欢迎广大.NET开发者来我们群一起讨论,研究.NET技术。(凑热闹的、其他语言开发人员以及喜欢涉及多门语言的误扰!)

#15楼  回复 引用   

2007-12-08 10:38 by tangkingthod[未注册用户]
一般吧,
http://www.javaworld.com/javaworld/jw-10-2000/jw-1027-pool.html
看看吧。。

#16楼  回复 引用   

2008-10-13 17:14 by Felix-Liu[未注册用户]
你的想法我非常同意
但是我實在不清楚你切割的Client Domain/Server Domain是什麼意思
是指一個User代表一個Client Domain?
還是指一個.aspx代表一個Client Domain?
我的理解是前者
那你所謂把DAL放在Sever Domain
是指把DAL那部份寫成Static (VB的shared)
所以Connection就可以共用嗎?
否則以Web 架構來說
本來每個page每個user都會建立connection
要把connection達到共享怎嚜做到?

#17楼  回复 引用   

2009-06-23 10:58 by DawningTiger[未注册用户]
你没看到人家是CS么?看清楚了再发问好不好。
数据库连接池对于connected layer固然很有用,但是有了disconnected layer,似乎也就没有那个必要了。