- 背景
- 前几天在评教的过程中出现了问题,当评教的人数越来越多的时候,服务器的压力也越来越大,CPU资源占用过多达到90%-100%左右,不知道是服务器配置过低,还是系统设计的有问题。
- 解决方法
- 通过综合分析各种可能的原因,首先,对服务器进行了一些设置,对资源使用进行一些限制。
- 设置应用程序池的回收时间为1720小时,也可以更改。
- CUP或内存超过多少之后,自动回收内存。
- 上面的设置是对于所有程序适用,不是针对某一个网站,这台服务器的配置应该可以运行起这个系统,很可能是程序中有些资源占用过多,于是检查了几遍代码是否有循环之类的问题,还有是对数据库访问的控制,大数据量的打开、关闭数据库是很占用时间、空间资源的。
- 使用连接池连接数据库
- 大多数 ADO.NET 对象使用连接池,以提高围绕 Microsoft 断开连接数据库的性能。
- 应用程序首先打开一个连接(或从连接池获得一个连接句柄),接着运行一个或多个SQL语句,然后处理,最后将连接释放回连接池。如果没有连接池,这些应用程序将花费许多额外时间来打开和关闭连接。
- 连接字符串
- ADO.Net 中的连接池大小可以通过数据库连接字符串来控制,例如:
- stringconStr ="server=192.168.24.165.;uid=sa;pwd=tcaccp;database=pubs;pooling=true;min pool size=5;max pool size=10".
- 其中 pooling 表示是否打开连接池,默认为打开,关掉时需要 pooling = false;
- min pool size 表示连接池最少保存几个连接对象;
- max pool size 表示连接池最多保存几个连接对象。(最大值不能为 0,也不能小于最小值);
- 最大连接数表示同时刻最多允许的访问的数量,可以起到保护站点的作用;最小表示即使没有访问也会打开几个连接。
- ADO.Net 中的连接池大小可以通过数据库连接字符串来控制,例如:
- 代码
#region 批量导入DataTable 未使用事务 /// <summary> /// 批量导入DataTable 未使用事务 /// </summary> /// <param name="dt">DataTable数据表</param> /// <param name="tableName">表名</param> /// <param name="dtColum">列名</param> public Boolean InsertTable(DataTable dt, string tableName, DataColumnCollection dtColum){ //打开数据库 GetConn(); try { //声明SqlBulkCopy ,using释放非托管资源 using (SqlBulkCopy sqlBC = new SqlBulkCopy(sqlConn)) { //一次批量的插入的数据量 //sqlBC.BatchSize = 1000; //超时之前操作完成所允许的秒数,如果超时则事务不会提交 ,数据将回滚,所有已复制的行都会从目标表中移除 //sqlBC.BulkCopyTimeout = 60; //設定 NotifyAfter 属性,以便在每插入10000 条数据时,呼叫相应事件。 //sqlBC.NotifyAfter = 10000; // sqlBC.SqlRowsCopied += new SqlRowsCopiedEventHandler(OnSqlRowsCopied); //设置要批量写入的表 sqlBC.DestinationTableName = tableName; //自定义的datatable和数据库的字段进行对应 //sqlBC.ColumnMappings.Add("id", "tel"); //sqlBC.ColumnMappings.Add("name", "neirong"); for (int i = 0; i < dtColum.Count; i++) { sqlBC.ColumnMappings.Add(dtColum[i].ColumnName.ToString(), dtColum[i].ColumnName.ToString()); } //批量写入 sqlBC.WriteToServer(dt); } // conn.Dispose(); //GetConn(); return true; } catch { return false; } finally { //关闭数据库 sqlConn.Close(); } } #endregion
向数据库中批量插入数据,这里用了using,自动关闭连接,不光能导入命名空间,还能在程序体内,局部使用某个对象。像上边代码,sqlCon 的作用域只有 using 对应的大括弧这么大。更神奇的是,using 可以在对象作用域结束时,自动调用 sqlCon.Dispose()将对象释放,所以以上代码中,没有 sqlCon.Close() 和 sqlCon.Dispose(),同样可以释放资源,放回连接池.- using详细用法:http://blog.csdn.net/zhangyingjie09/article/details/8876451
- 监控连接池的状态
- 监控连接池有多种方法,这里主要介绍两种比较常用的,每种方法的侧重点是不同的,所以,也没有谁好谁坏。
- 通过监控驱动程序获得连接池状况
- 我的电脑(右键)-->管理-->系统工具-->性能日志和警报-->计数器日志上点击右键,新建日志设置,随便起名 abc,出现设置对话框,“添加对象”,下拉列表中选 “.NET
Data Provider for SqlServer”,添加,关闭。如下图
- 数据采样间隔,比如 1 秒采集一次。切换到“日志文件”选项卡,将日志文件类型设置为“文本文件(逗号分隔)”,日志就会默认记录在“C:PerfLogsabc_000001.csv”里,点确定关闭窗体。
- 回到“日志计数窗体”,如果添加的日志为绿色表示,已经启动。
- 我的电脑(右键)-->管理-->系统工具-->性能日志和警报-->计数器日志上点击右键,新建日志设置,随便起名 abc,出现设置对话框,“添加对象”,下拉列表中选 “.NET
Data Provider for SqlServer”,添加,关闭。如下图
- SQL Profiler事件探查器
- 事件探查器的功能是监视SQL Server数据库系统引擎事件,主要用于监视SQL SERVER系统的运行性能。
- Profiler可以用来捕获发送到SQL Server的所有语句以及语句的执行性能相关数据(如语句的read/writes页面数目,CPU的使用量,以及语句的duration等)以供以后分析。
- 调试SQL语句、存储过程、识别执行慢的语句。如下图
- 设置模板
- 分析数据
- 设置模板
- 大多数 ADO.NET 对象使用连接池,以提高围绕 Microsoft 断开连接数据库的性能。
- 连接池是一个很好的程序功能,帮助程序管理大量数据库连接,但你是否会有效的管理连接池对于连接池是不是发挥出好的作用至关重要,就像一个企业有很多高手是不够,还需要一个好的管理者来管理,才能让他们发挥最大的价值。
- 通过综合分析各种可能的原因,首先,对服务器进行了一些设置,对资源使用进行一些限制。
- 总结
- 开发系统的时候应该做一部分,调试一部分,便于以后维护
- 分析软件使用目的:是否涉及到性能问题,如果对性能要求高的系统,需要考虑下性能。