1:背景
最近公司說,咱們業務系統那么多,每個系統都在寫自己的日志,不方便查看和管理。
於是,想搞個日志收集系統。
2:構思
3:實現
a):收集服務
收集服務采用ServiceStack框架,提供web api 的方式訪問。
客戶端調用服務,直接把日志信息丟到消息隊列中

public AopResult<Int32> Get(LogRequest obj) { if (obj == null) return AopResult.Fail<Int32>("參數不正確!"); if (string.IsNullOrEmpty(obj.AppNo)) return AopResult.Fail<Int32>("請提供應用編號!"); if (string.IsNullOrEmpty(obj.Tag)) return AopResult.Fail<Int32>("請提供應用標簽!"); if (string.IsNullOrEmpty(obj.Content)) return AopResult.Fail<Int32>("請提供日志內容!"); LogQueueHelper.EnQueue(ParserImp.Parser(obj)); return AopResult.Success(0); }
b):讀取日志並創建寫入任務
考慮到日志量過大,需要分表的操作,因此,在日志系統中,創建一個基表。
基表的數據包括,日志應用,標簽,隊列名,表名,創建日期,是否啟用等信息

public class QueueKey { /// <summary> /// MongoDB 默認主鍵 /// </summary> public string _id { get; set; } /// <summary> /// 隊列名 /// </summary> public string Key { get; set; } /// <summary> /// 應用 /// </summary> public string AppNo { get; set; } /// <summary> /// 標簽 /// </summary> public string Tag { get; set; } /// <summary> /// 當前集合名稱 /// </summary> public string CollectionName { get; set; } /// <summary> /// 是否啟用 /// </summary> public bool Enabled { get; set; } /// <summary> /// 創建時間 /// </summary> public DateTime CreateTime { get; set; } }
創建一個任務,定時執行從隊列中讀取日志信息,並根據基表數據(緩存中),創建寫入。並把寫入任務放入到任務隊列中。

public static void FlushLog() { while (true) { try { if (LogQueueHelper.QueueKeys.Any()) { //判斷是否需要分庫 var needRe = DateTime.Now.ToString("dd") == "01"; for (var i = 0; i < LogQueueHelper.QueueKeys.Count; i++) { var queueKey = LogQueueHelper.QueueKeys[i]; if (needRe) queueKey = DbHelper.RefreshQueueKey(queueKey); var queue = LogQueueHelper.Logs[queueKey.Key]; var length = queue.Count; var m = 0; var lst = new List<LogContent>(); while (m < length) { m++; lst.Add(queue.Dequeue()); } TaskHelper.AddTask(() => DbHelper.Insert(lst, queueKey)); } } } finally { Thread.Sleep(Config.QueueConfig.QueueSleep); } } }
c):執行日志寫入任務
創建一個任務集合,每隔2S鍾,從任務隊列中添加一個任務到集合,上限為5個。
在添加任務到集合之前,判斷集合中的任務,如果大於等於5個,則判斷准備移除集合中已完成的任務。移除失敗,跳出循環,繼續下次執行。移除成功,則從隊列中,取出下一個任務,啟動后,添加到集合中

public static void RunTask() { while (true) { Thread.Sleep(2 * 1000); if (RunTasks.Count >= 5) { var task = RunTasks.FirstOrDefault(p => p.IsCompleted); if (task == null) continue; task.Dispose(); RunTasks.Remove(task); } if (QueueTasks.Count > 0) { var task = QueueTasks.Dequeue(); task.Start(); RunTasks.Add(task); } } }
4:結束
這是一個簡陋的日志收集系統,歡迎大神拍磚,讓我改進。