通過過濾器實現性能監控(含源碼)


源碼:

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歡迎大家提出您的建議。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM