在开发社区网站时必须考虑的一个问题是网络用户的并发请求,除了增加Cache和静态化Html的常用手段外,优化Database的tables关系,及SQL 语句也是相当重要,但用户的并发请求Pages,常常会导致一些复杂业务的查询会有可能会出现Sql Connection Time out的错误,用户的并发请求用光了数据库的连接池,怎么办呢,要从根上解决问题是件不太好做的事,涉及的面和相关技术也很多,有数据库结构本身的问题也有代码的问题,也有服务器硬件的问题,但如果出现了以上的问题肯定会出现"红屏",这对于系统来说是一个大禁,这样的用户体验太差了,出现这样的错误对于用户来说是很不爽,对于专业的开发人员肯定认为这个网站技术做的不好,烂,那如何去解决这个问题,直接切入点就是把数据库的连接池管理起来,在代码里控制数据库的接个池大小,而不时由用户直接去请求数据库的连接池,中间业务逻辑上加一层来现对数据库连接的管理。
基本思路是这样,可以用泛型来做一个数据字典,实现对Sqlconnection的集合的维护。
基本过程:
当用户请求SqlConnection时,先从可用的连接池中取出可用的SqlConnection连接直接返回经人用户,并且把当前正在用的SqlConnection设为锁定不可用状态。如果池中没有任何可用的,那么直接重新生成一个新的SqlConnection.
当用户用完这个SqlConnection后,把它重新放回到池中等下一次请求。
同样用一个线程去跟踪池中可用连接串的状态,如果它的等待请求时间超过一个时间段如(从它的创建时间到它未使用的间隔时间一分钟未收到用户的请求)那么执行Close方法,让他回收到DataBase的连接池中。
注意ADO.net的SqlConnection的Close方法,其实并不是在物理上关闭连接,你可以用sp_who看是否还存在你的请求,只不过它的状仿是sleeping状态,只有等到没有用户请求,超过了他的过期时间后自动会消失释放资源,当然也可以在c#中释放非托管一SqlConnection资源,要通知GC回收。
DataAccess.ObjectPool.objectPool是用泛型来现实现的一个字典
基本代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DataAccess.DbConn
{
/// <summary>
/// 数据库连接对象池
/// </summary>
public class DBConn : DataAccess.ObjectPool.objectPool<SqlConnection>
{
/// <summary>
/// 私有构造函数
/// </summary>
private DBConn()
{
}
/// <summary>
/// 返回自身对象(Singleton)
/// </summary>
public static readonly DBConn Instance= new DBConn();
/// <summary>
/// 默认连接语句
/// </summary>
//public static string DbPoolConnStr = DataAccess.BaseDAO.CONN_STRING_NON_DTC;
private string DbPoolConnStr
{
get
{
return DataAccess.BaseDAO.CONN_STRING_NON_DTC;
}
}
private static int _PoolMaxCount = 10;
/// <summary>
/// Gets or sets the pool max count.
/// </summary>
/// <value>The pool max count.</value>
public new int PoolMaxCount
{
get
{
return _PoolMaxCount;
}
set
{
base.PoolMaxCount = _PoolMaxCount;
_PoolMaxCount = value;
}
}
/// <summary>
/// 创建数据库连接对象
/// </summary>
/// <returns>已打开的数据库连接对象</returns>
protected override SqlConnection Create()
{
SqlConnection conn = new SqlConnection(DbPoolConnStr);
conn.Open();
return conn;
}
/// <summary>
/// 验证连接状态
/// </summary>
/// <param name="t">数据库连接对象</param>
/// <returns>连接状态Open : true Close:false</returns>
protected override bool ValiDate(SqlConnection t)
{
try
{
return !(t.State.Equals(ConnectionState.Closed));
}
catch (SqlException)
{
return false;
}
}
/// <summary>
/// 关闭数据库连接
/// </summary>
/// <param name="t">数据库连接对象</param>
protected override void Expire(SqlConnection t)
{
try
{
if (t.State == ConnectionState.Open)
{
t.Close();
}
}
catch (SqlException)
{
}
}
/// <summary>
/// 从池中获取数据库连接
/// </summary>
/// <returns>数据库连接对象</returns>
public SqlConnection BorrowDBConn()
{
try
{
return base.GetObjectFromPool();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 将连接对象放入池中
/// </summary>
/// <param name="conn">数据库连接对象</param>
public void ReturnDBConn(SqlConnection conn)
{
base.ReturnObjectToPool(conn);
}
}
}
因为懂得所以慈悲 leung
基本思路是这样,可以用泛型来做一个数据字典,实现对Sqlconnection的集合的维护。
基本过程:
当用户请求SqlConnection时,先从可用的连接池中取出可用的SqlConnection连接直接返回经人用户,并且把当前正在用的SqlConnection设为锁定不可用状态。如果池中没有任何可用的,那么直接重新生成一个新的SqlConnection.
当用户用完这个SqlConnection后,把它重新放回到池中等下一次请求。
同样用一个线程去跟踪池中可用连接串的状态,如果它的等待请求时间超过一个时间段如(从它的创建时间到它未使用的间隔时间一分钟未收到用户的请求)那么执行Close方法,让他回收到DataBase的连接池中。
注意ADO.net的SqlConnection的Close方法,其实并不是在物理上关闭连接,你可以用sp_who看是否还存在你的请求,只不过它的状仿是sleeping状态,只有等到没有用户请求,超过了他的过期时间后自动会消失释放资源,当然也可以在c#中释放非托管一SqlConnection资源,要通知GC回收。
DataAccess.ObjectPool.objectPool是用泛型来现实现的一个字典
基本代码如下:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DataAccess.DbConn
{
/// <summary>
/// 数据库连接对象池
/// </summary>
public class DBConn : DataAccess.ObjectPool.objectPool<SqlConnection>
{
/// <summary>
/// 私有构造函数
/// </summary>
private DBConn()
{
}
/// <summary>
/// 返回自身对象(Singleton)
/// </summary>
public static readonly DBConn Instance= new DBConn();
/// <summary>
/// 默认连接语句
/// </summary>
//public static string DbPoolConnStr = DataAccess.BaseDAO.CONN_STRING_NON_DTC;
private string DbPoolConnStr
{
get
{
return DataAccess.BaseDAO.CONN_STRING_NON_DTC;
}
}
private static int _PoolMaxCount = 10;
/// <summary>
/// Gets or sets the pool max count.
/// </summary>
/// <value>The pool max count.</value>
public new int PoolMaxCount
{
get
{
return _PoolMaxCount;
}
set
{
base.PoolMaxCount = _PoolMaxCount;
_PoolMaxCount = value;
}
}
/// <summary>
/// 创建数据库连接对象
/// </summary>
/// <returns>已打开的数据库连接对象</returns>
protected override SqlConnection Create()
{
SqlConnection conn = new SqlConnection(DbPoolConnStr);
conn.Open();
return conn;
}
/// <summary>
/// 验证连接状态
/// </summary>
/// <param name="t">数据库连接对象</param>
/// <returns>连接状态Open : true Close:false</returns>
protected override bool ValiDate(SqlConnection t)
{
try
{
return !(t.State.Equals(ConnectionState.Closed));
}
catch (SqlException)
{
return false;
}
}
/// <summary>
/// 关闭数据库连接
/// </summary>
/// <param name="t">数据库连接对象</param>
protected override void Expire(SqlConnection t)
{
try
{
if (t.State == ConnectionState.Open)
{
t.Close();
}
}
catch (SqlException)
{
}
}
/// <summary>
/// 从池中获取数据库连接
/// </summary>
/// <returns>数据库连接对象</returns>
public SqlConnection BorrowDBConn()
{
try
{
return base.GetObjectFromPool();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 将连接对象放入池中
/// </summary>
/// <param name="conn">数据库连接对象</param>
public void ReturnDBConn(SqlConnection conn)
{
base.ReturnObjectToPool(conn);
}
}
}
因为懂得所以慈悲 leung