事件由来,这段时间,接手公司充值系统,经过一段时间发现,由于供应商原因,经常会出现充值失败,而充值订单量很大,在短时间内就会出现大量客户投诉,而系统不能及时作出响应,前些天,我在修改充值系统时就在可能会出异常的地方,进行异常处理,并且把异常信息以邮件形式发送出来,这样技术人员就可以及时处理充值系统遇到了问题,这样又带来一个新的问题,异常邮件短时间内出现太多,影响了充值系统正常的邮件的发送。
首先看一下充值系统的架构情况,如下图所示
Top.WEB端供客户使用,通过T op.WCF把客户充值订单提交到Platform数据库里。
WIN Service每秒钟从Platform数据库订单查询出来,根据类型送到三家供应商去充值。
比如说,如果充值供应商1内部出现了问题,导致提交到充值供应商1的订单就不能充值成功,订单量很大的情况下,短时间内就出现了大量的异常邮件,而Mail Service由于充值供应商1的原因,其它供应商充值正常的邮件不能及时发送出来,比如供应商2,3充值失败,需要通知客服部门帮客户补充的订单不能及时发送给客服部门。
刚开始,其它同事也提到过,在Win Service程序里加个计数功能,突然出现大量异常情况就不再发送这种异常邮件了,这样也有问题,就是,这次不发送了,处理好了以后,再一次出现异常时还是要发送这种异常邮件的,当达到计数的限额以后就不再发送。达到这样的效果需要人工重启一下Win Service程序才可以。
下边我就想通过充值系统自身能实现异常邮件自动开关的功能,类图设计如下
AlertSwitch.Alert_TimePeriod 表示时间段,单位是分钟
AlertSwitch._Alert_Count 表示时间段内产生多少封邮件
AlertSwitch.Switch是开关,0表示开,1表示关
以上变量都是Static型 的
AlertSwitch.OperAddAlert()方法,是往List<Alert>新增一条记录,并且当Alert_TimePeriod时间段内出现超过._Alert_Count数量的警报邮件时就把开关关掉,如果不就把开关开着,原代码如下
{
public static List<DFAlert> dfalert;
private static int _Alert_TimePeriod = Settings.Default.Alert_TimePeriod;//从配置文件中读取,默认为2
private static int _Alert_Count = Settings.Default.Alert_Count ; //从配置文件中读取,默认为20
private static readonly ILog DFSubmitLog = LogManager.GetLogger("DFSubmitLog");
//开关 0 开,1 关
public static int Switch;
//public DFAlertSwitch()
//{
// dfalert = new List<DFAlert>();
//}
/// <summary>
/// 新增一条Alert,并且判断开关
/// </summary>
/// <param name="_dfalert"></param>
public static void AddAlert(DFAlert _dfalert)
{
if (dfalert == null)
{
dfalert = new List<DFAlert>();
}
DFSubmitLog.InfoFormat("head : ",_dfalert.AlertHead);
DFSubmitLog.InfoFormat("Time : ", _dfalert.AlertTime);
dfalert.Add(_dfalert);
DFSubmitLog.Info("已经添加");
DFSubmitLog.InfoFormat("Count : ", dfalert.Count);
if (dfalert.Count > _Alert_Count)//当邮件超过20封时,开始判断
{
dfalert.RemoveAt(0);//把第一个移除
if (dfalert[dfalert.Count-1].AlertTime.AddMinutes(- _Alert_TimePeriod) <= dfalert[0].AlertTime) //当前第20封邮件的时间 和第一封邮件的时间做比较
{
//如果比较时间 在 2 分钟以内,说明 在2分钟内,突然产生了20封以上的邮件 这时候可能系统出现异常,不能再发警报邮件了
//把开关设置为关闭
Switch = 1;
}
else
{
Switch = 0;
}
}
}
}
public class DFAlert
{
public string AlertHead
{
get;
set;
}
public DateTime AlertTime
{
get;
set;
}
public DFAlert(string alerthead, DateTime alerttime)
{
AlertHead = alerthead;
AlertTime = alerttime;
}
}
客户端调用示例程序如下
DFAlertSwitch.AddAlert(_dfalert);
if (DFAlertSwitch.Switch == 1)
{
return; //如果开关关掉,直接退出发邮件。
}
else
{
//nothing;
}