源碼:
https://github.com/wyl1924/Perfmon
前言:
由於最近系統訪問量過大,相關系統間處理不同步,造成相互等待時間較長,影響系統整體運行性能,造成用戶明顯感覺響應時間慢、體驗不好。所以就對每一個模塊的訪問人數加一控制。
進而決定用過濾器與redis。
1.設置最大訪問人數:
此頁面在數據存在redis中。當頁面打開時如果redis中頁面數據為空,則進行數據初始化。沒有設置添加頁面,具體原因嗎?因為控制的模塊是固定的,當添加模塊式,直接添加redis頁面數據即可。有點不合理哈,不過先這樣處理吧。
設置效果圖
1.1.redis的操作:
我喜歡用redis存緩存信息,如果你喜歡用mongodb或其他方式都可以。以前的文檔中已經有過類似的操作,在這再寫一下。
1.1.1.redis連接基類
每次操作redis繼承此基類即可.
public abstract class RedisHelper
{
private IRedisClient _client;
private string _configuration_string;
public RedisHelper()
{
}
public RedisHelper(string configuration_string)
{
this._configuration_string = configuration_string;
}
public void set_configuration_string(string configuration_string)
{
this._configuration_string = configuration_string;
}
public IRedisClient rs
{
get
{
if (string.IsNullOrWhiteSpace(this._configuration_string))
{
return null;
}
if (this._client == null)
{
this._client = new RedisClient(this._configuration_string);
}
return this._client;
}
}
}
}
1.1.2.項目中redis的使用
(1)配置文件
其中路徑可以直接寫服務器ip地址。我把他寫成字符串,是為了開發環境和正是環境都不用修改程序,直接做ip映射就行了。

(2)連接redis服務器
public class DbPerfmon : RedisHelper
{
public DbPerfmon()
: base()
{
string myredis = ConfigurationManager.AppSettings["Redis_Server_Url_Perfmon"].ToString();
set_configuration_string(myredis);
}
1.1.3.數據操作【獲取各模塊訪問數據,設置最大訪問數,刪除指定redis數據】
(1)其中Loginname為redis key值。【一個人同時只能操作一個模塊】
(2)模塊名稱為redis value值
注:簡單說一下具體方法:
(1)(bool SetMaxTimes(string code, string name, int times)
此方法用作設置每個模塊訪問最大人數,其中code是模塊名稱。【代碼的實現歡迎大家給點中肯的建議】
(2)List<PerfmonModel> GetPerfmons()
這是上邊頁面展示數據集的獲得,不再累述
(3)bool PagePush(string ModuleName, string LoginUserName)
核心方法,如果訪問人數小於最大訪問人數。當前把當前訪問人及模塊存入redis
(4) bool PageRemove(string LoginUserName)
當執行方法執行結束時觸發,移除redis中訪問人信息。
public class DbPerfmon : RedisHelper { public DbPerfmon() : base() { string myredis = ConfigurationManager.AppSettings["Redis_Server_Url_Perfmon"].ToString(); set_configuration_string(myredis); } public bool SetMaxTimes(string code, string name, int times) { try { List<PerfmonTime> list = new List<PerfmonTime>(); string key = code; using (rs) { PerfmonTime time = new PerfmonTime() { name = name, code = code, maxTimes = times }; ; if (rs.Get<List<PerfmonTime>>("Perfmon") == null) list.Add(time); else if (list.Exists(l => l.code == code && l.name == name)) { list = rs.Get<List<PerfmonTime>>("Perfmon"); list.Add(time); } else { list = rs.Get<List<PerfmonTime>>("Perfmon"); list.RemoveAll(l => l.code == code && l.name == name); list.Add(time); } var flag = rs.Set<List<PerfmonTime>>("Perfmon", list); } return true; } catch (Exception ex) { return false; } } public List<PerfmonModel> GetPerfmons() { List<PerfmonModel> list = new List<PerfmonModel>(); using (rs) { var PerfmonTime = rs.Get<List<PerfmonTime>>("Perfmon"); if (PerfmonTime == null || PerfmonTime.Count < 1) return null; PerfmonTime.ForEach(p => list.Add(new PerfmonModel { name = p.name, code = p.code, maxTimes = p.maxTimes, nowTimes = ModulCount(p.code) }) ); } return list; } int ModulCount(string ModuleName) { List<string> keylist = rs.SearchKeys("*"); //得到集合 int count = 0; IDictionary<string, object> list = rs.GetAll<object>(keylist); count = list == null ? 0 : list.Where(l => l.Value.ToString() == ModuleName).Count(); return count; } public bool PagePush(string ModuleName, string LoginUserName) { using (rs) { var PerfmonTime = rs.Get<List<PerfmonTime>>("Perfmon"); if (PerfmonTime == null) return false; else if (!PerfmonTime.Exists(l => l.code == ModuleName)) return false; int maxTime = PerfmonTime.Where(p => p.code == ModuleName).ToList()[0].maxTimes; //得到所有的Key List<string> keylist = rs.SearchKeys("*"); //得到集合 IDictionary<string, object> list = rs.GetAll<object>(keylist); int count = 0; count = list == null ? 0 : list.Where(l => l.Value.ToString() == ModuleName).Count(); //foreach (KeyValuePair<string, object> kv in list) //{ // if (kv.Value == ModuleName) // { // count++; // } //} if (maxTime < count) return false; //return rs.Set(LoginUserName, ModuleName, DateTime.Now.AddMinutes(30)); return rs.Set(LoginUserName, ModuleName); } } public bool PageRemove(string LoginUserName) { using (rs) { return rs.Remove(LoginUserName); } } }
2.利用過濾器進行模塊監控
c#中過濾器在這不再累述。准備在以后c#特性中進行詳細敘述。分別在方法執行前與方法執行后進行調用上邊的方法。
2.1.OnActionExecuting
判斷當前訪問人數是否大於指定訪問人數,不大於則加一,繼續action
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var filer = new DbPerfmon().PagePush(ModuleName, LoginUserName);
if (filer)
base.OnActionExecuting(filterContext);
else
{
ContentResult cr = new ContentResult();
//cr.Content = "<script>window.location.href='" + HttpContext.Current.Request.UrlReferrer.OriginalString + "';</script>";
cr.Content = "<p style='color:Red;font-weight:bold;clear:both'>同時操作此業務人員較多,請稍候再試。</p>";
filterContext.Result = cr;
}
}
2.2.OnResultExecuted
action執行后,刪除該訪問人數redis信息
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
base.OnResultExecuted(filterContext);
new DbPerfmon().PageRemove(LoginUserName);
}
2.3.服務系統出現異常時
此方法是后續加的,沒有過多的測試。
public class ExceptionFilterAttribute : HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { base.OnException(filterContext); ContentResult cr = new ContentResult(); //cr.Content = "<script>window.location.href='" + HttpContext.Current.Request.UrlReferrer.OriginalString + "';</script>"; cr.Content = "<p style='color:Red;font-weight:bold;clear:both'>此功能頁面異常,請聯學系校管理員或稍候再試。</p>"; filterContext.Result = cr; } }
在此把代碼貼出:https://github.com/wyl1924/Perfmon歡迎大家提出您的建議。。
