做网站运维的人,几乎都有过这样的经历:网站流量稍微上来一点,数据库连接数就蹭蹭往上涨,IIS服务器CPU直接飙到90%以上,页面打开慢得像蜗牛爬。你翻日志、查代码、重启应用池,折腾半天发现是数据库连接池没配好。这事我碰到过太多次了,今天就专门聊聊IIS下数据库连接池怎么优化。

先搞清楚一个问题,连接池到底是干嘛用的。每次程序要操作数据库,都得先建立一条连接,用完再断开。这个建立和断开的过程非常消耗资源,尤其是SQL Server这类重量级数据库,一次连接握手的开销比执行几条SQL还大。连接池的思路就是把这些连接缓存起来,谁要用谁拿,用完还回来,省掉反复建立断开的开销。IIS里跑.NET程序,默认用的就是System.Data.SqlClient,这个组件自带连接池功能,但默认配置往往不是最优的。
我见过最典型的错误是,连接池没设上限,或者设得太大。默认情况下,连接池最大连接数是100,最小是0。有些开发同学图省事,把Max Pool Size设成500甚至1000,觉得越多越保险。结果呢?高并发一来,SQL Server被几百条连接同时打过来,内存暴增,锁竞争加剧,查询性能反而直线下降。连接池不是越大越好,要跟数据库的承受能力匹配。SQL Server默认最大并发连接数是32767,听起来很多,但每个连接都要占用内存和线程,实际能扛住的并发连接数远低于这个数字。
再说连接池的复用机制。连接池里的连接是按连接字符串区分的,包括服务器地址、数据库名、用户名、密码,甚至Application Name,任何一个参数不同,都会创建独立的连接池。很多团队在代码里动态拼连接字符串,或者每次new一个SqlConnection都带上不同的参数,结果连接池完全没起作用,每条连接都是新建的,性能自然上不去。正确的做法是,连接字符串统一放配置文件里,保持不变,这样连接池才能有效复用。
还有一个常见坑是连接泄漏。程序里开了连接没关闭,或者关闭顺序不对,连接就永远回不到池里。一旦池里的连接被耗尽,新的请求就只能排队等待,表现就是网站卡死、超时。排查方法很简单,用性能计数器看NumberOfPooledConnections和NumberOfActiveConnections,如果活跃连接数持续居高不下,八成是有连接泄漏。解决思路是确保所有数据库操作都用using语句包裹,或者在finally里关闭连接,千万别图省事只Close不Dispose。
超时设置也值得细调。默认的连接超时是15秒,命令超时是30秒。如果数据库偶尔慢一下,程序就要傻等15秒才报错,用户体验极差。但也不是说超时设得越短越好,太短了正常的慢查询也会被掐断。建议根据实际业务情况调整,一般连接超时设在5到10秒,命令超时设在10到20秒比较合适。同时要配合重试机制,避免一次超时就把整个请求打挂。
IIS本身的应用池回收策略也会影响连接池。默认情况下,IIS应用池闲置20分钟就会回收,回收意味着进程重启,所有连接池里的连接全部清空。如果网站访问量不大,经常处于闲置状态,那么每次有用户访问时,都要重新建立数据库连接,性能自然好不了。解决办法是在应用池的高级设置里,把闲置超时时间调长,或者干脆设为0(永不超时)。但要注意,应用池长时间不回收也可能导致内存泄漏累积,所以最好在凌晨低峰期设置定时回收。
还有一个容易被忽略的点是SQL Server端的状态。连接池里的连接虽然物理上保持着,但如果SQL Server重启了,或者网络闪断,这些连接其实已经失效了。程序拿到失效的连接去执行SQL,会报“连接已关闭”或者“管道已断开”之类的错误。解决办法是在连接字符串里加上Connection Lifetime,比如设为300秒,超过这个时间的连接会被池自动清理重建。另外,SqlConnection有个ClearPool方法,可以在捕获到连接异常时手动清空连接池,强制重新建立连接。
我建议的做法是,先用性能监控工具摸清现状。Windows自带的性能监视器里,可以添加.NET Data Provider for SqlServer相关的计数器,看看连接池的实际使用情况。观察一段时间,记录下峰值并发、平均连接数、池内空闲连接数这些指标,再针对性地调整配置。一般来说,Max Pool Size设为峰值并发的1.5到2倍就够用了,Min Pool Size可以设个5到10,避免冷启动时频繁建连。
再补充一个细节,数据库连接字符串里的Pooling参数,默认是true,但有些框架或者ORM可能默认把它关掉了。比如某些版本的Entity Framework,如果配置不当,会绕过连接池直接建连。检查方式很简单,看连接字符串里有没有Pooling=false,有的话去掉就行。另外,如果项目用了Dapper或ADO.NET,确认所有查询都走同一个连接字符串,这样才能保证连接池命中率。
优化完之后,效果是立竿见影的。我之前帮一个电商客户调过,他们网站高峰期每秒请求大概2000次,数据库连接数飙到600多,CPU持续100%。调整了Max Pool Size到300,加上了Connection Lifetime,修掉了两处连接泄漏,再把应用池回收策略改了一下,CPU降到了40%左右,页面响应时间从平均3秒降到了800毫秒。这就是连接池优化的威力。
说一句,连接池优化不是一劳永逸的事。网站的业务在变,流量在变,数据库配置也在变,每隔一段时间就要重新审视一遍连接池的设置。把这个当成日常运维的一部分,别等到网站卡死了才想起来查。IIS下的数据库连接池,本质上就是个资源调度的活,调好了网站飞起,调不好服务器天天报警。


