问题缘起:收到运维同事发来的邮件,说自上次网站更新后,CPU使用率上升趋势明显(下图中红框部分所示),但网站访问数并没有增加。
问题排查:是什么原因导致CPU使用率上升呢?肯定是某个访问量比较大的页面进行了耗CPU的操作,如文件读写、内存中的一些复杂运算等。结合上次网站更新内容,将问题锁定在了房源详情页。主要涉及到读xml文件(最大的有2M多)到DataTable中,每次打开页面时根据DataTable中的两个列值判断在这个DataTable中有没有,比较严重的是读文件没加缓存,造成了频繁的读文件,使CPU一直处于忙碌状态。
找到了问题所在,修改起来就容易多了,增加缓存就好了,下面是修改后的伪代码。修改之后更新网站,CPU使用率又恢复到正常值了(红框后面的部分)。
简单代码示例
/// <summary>
/// 获取置业专家列表
/// </summary>
/// <returns>置业专家列表</returns>
public static DataTable GetAgentXML()
{
DataTable dt = null;
string cacheName = "agentall_zyzj";
if (CacheManager.IsCached(cacheName))
{
object o = CacheManager.GetCache(cacheName);
if (o != null)
{
dt = o as DataTable;
}
}
if (dt == null)
{
//读取xml文件到DataTable中
dt = GetAgentXMLFromFile();
if (dt != null)
{
try
{
if (dt.Rows.Count > 0)
{
dt.PrimaryKey = new DataColumn[] { dt.Columns["newcode"], dt.Columns["agentid"] };
}
}
catch
{ }
CacheManager.InsertCache(cacheName, dt, System.DateTime.Now.AddMinutes(60));
}
}
return dt;
}
/// <summary>
/// 判断是否为置业专家
/// </summary>
/// <returns>是否为置业专家</returns>
public static bool CheckZyzj(long agentID, long newCode)
{
DataTable Agentdt = new DataTable();
bool isZyzj = false;
try
{
Agentdt = GetAgentXML();
if (Agentdt != null && Agentdt.Rows.Count > 0)
{
DataRow[] drs = Agentdt.Select(" agentid=" + agentID + " and newcode=" + newCode);
if (drs != null && drs.Length > 0)
{
isZyzj = true;
}
}
}
catch (Exception ex)
{
isZyzj = false;
}
return isZyzj;
}
需要特别说明的一点,此次优化在增加缓存的同时,还做了一个小调整,将数据从xml文件读到DataTable后,为DataTable设置了主键“dt.PrimaryKey = new DataColumn[] { dt.Columns["newcode"], dt.Columns["agentid"] }”,为DataTable设置主键可以大大提高select查询效率(这点有些类似于数据库中表的主键)。因为这次修改了两个地方,增加主键的效率不好用数据说明。但之前做过一个复杂报表的生成,在内存中要对DataTable做大量查询,简单的增加主键后,效率提升了七八倍。
缓存在编程中至关重要,网站访问量小时缓存与否影响不大,一旦量上来了,再简单的逻辑也需要多考虑,平日里要多有些思想意识在里头,才会有预见性,减少上线后出现问题的几率。