• 使用MongoDB 记录业务日志


          最近公司有个需求,要对业务日志进行记录并根据日志排查问题,以前都是使用log4net之类的日志组件来记录到文件,这种方式已经不能满足业务的需要,因为日志文件会很大,即使进行分割后,查找也是很不方便,何况现在项目基本都是分布式,会有多台应用服务器,那么就需要把多台服务器上的日志弄到一起,十分的麻烦,经过选择后ELK进入视线,测试环境也搭建了一套,现在唯一的问题就是怎么把多台服务器上的日子泵出到elstaticsearch中,我们的应用服务器都是windows,所以需要在每一台应用服务器上安装一个服务,如:NXlog之类的,经过考虑觉得这种方式太麻烦,所以决定把日志先记录到MongoDb,先实现简单的日志查询,再统一从MongoDb将数据泵出到elstaticsearch中,思路有了,开始动手测试。

    第一步,插入测试数据,MongoDb数据库我是安装在本地一个linux虚拟机里,插入1000000条数据耗时8分钟,有兴趣的童鞋自己测试一下,用来存储日志完全没有问题,废话不多说了,上代码:

     1         static void Main(string[] args)
     2         {
     3             try
     4             {
     5 #region 插入测试数据
     6                 //var sw = new Stopwatch();
     7                 //sw.Start();
     8                 //string tableName = "InsuranceLog";
     9                 //for (var i = 0; i < 1000000; i++)
    10                 //{
    11                 //    var lb = new LogBase<InsuranceLog>()
    12                 //    {
    13                 //        Message = new InsuranceLog
    14                 //        {
    15                 //            BusinessKey = i.ToString(),
    16                 //            BusinessName = "政策查询" + i,
    17                 //            BusinessParameters = "根据实际需要组织<xml><OrderId>AutoHome" + i + "</OrderId></xml>"
    18                 //        }
    19                 //    };
    20 
    21                 //    InsertOneLogToMongoDbAsync(lb, tableName);
    22                 //}
    23                 //sw.Stop();
    24                 //Console.WriteLine("插入100000条数据耗时:" + sw.ElapsedMilliseconds + "ms");
    25 #endregion
    26 
    27 #region 根据条件从1000000条数据中获取指定数据
    28                 var sw = new Stopwatch();
    29                 sw.Start();
    30                 var obj = GetList();
    31                 sw.Stop();
    32                 Console.WriteLine("从100000条数据获取指定数据耗时:" + sw.ElapsedMilliseconds + "ms");
    33                 foreach (var o in obj)
    34                 {
    35                     if (o.Message != null)
    36                     {
    37                         Console.WriteLine("调用时间:"+o.CallTime);
    38                         Console.WriteLine("业务key:" + o.Message.BusinessKey);
    39                         Console.WriteLine("业务名称:" + o.Message.BusinessName);
    40                         Console.WriteLine("业务参数:" + o.Message.BusinessParameters);
    41                     }
    42                 }
    43 #endregion
    44                 Console.ReadKey();
    45             }
    46             catch (Exception ex)
    47             {
    48                 throw;
    49             }
    50         }
    51 
    52 
    53         /// <summary>
    54         /// 从MongoDb 获取数据
    55         /// </summary>
    56         /// <returns></returns>
    57         static List<LogBase<InsuranceLog>> GetList()
    58         {
    59             try
    60             {
    61                 var client = new MongoClient("mongodb://192.168.21.129:27017");
    62                 var database = client.GetDatabase("logs");
    63                 var collection = database.GetCollection<LogBase<InsuranceLog>>("InsuranceLog");
    64                 var b = (from x in collection.AsQueryable()
    65                          where x.CallTime.StartsWith("201604281414")
    66                          && x.CallTime.EndsWith("000")
    67                          select x).ToList();
    68                 return b;
    69             }
    70             catch (Exception ex)
    71             {
    72                 throw;
    73             }
    74         }
    75 
    76 
    77         /// <summary>
    78         /// 插入单条数据
    79         /// </summary>
    80         /// <typeparam name="T"></typeparam>
    81         /// <param name="t"></param>
    82         /// <param name="name"></param>
    83         static async Task InsertOneLogToMongoDbAsync<T>(T t, string name)
    84         {
    85             try
    86             {
    87                 var client = new MongoClient("mongodb://192.168.21.129:27017");
    88                 var database = client.GetDatabase("logs");
    89                 var collection = database.GetCollection<T>(name);
    90                 await collection.InsertOneAsync(t);
    91             }
    92             catch (Exception ex)
    93             {
    94                 throw;
    95             }
    96         }

    主要测试点在查询上,要根据条件快速检索出需要的数据,我测试了一下,单条数据大概是800ms左右,我的查询条件取出来38条数据,耗时842ms,

    重点:日志基类,扩展性很好,支持自定义实体类

     1     /// <summary>
     2     ///     日志基类
     3     /// </summary>
     4     [BsonIgnoreExtraElements]
     5     public class LogBase<T>
     6     {
     7         public LogBase()
     8         {
     9             CallTime = DateTime.Now.ToString("yyyyMMddHHmmssfff");
    10             SerialNo = Guid.NewGuid().ToString("N");
    11             ClientType = "1";
    12             Message = default(T);
    13             var myEntry = Dns.GetHostEntry(Dns.GetHostName());
    14             var address = myEntry.AddressList.FirstOrDefault(e => e.AddressFamily.ToString().Equals("InterNetwork"));
    15             if (address == null) return;
    16             var ip = address.ToString();
    17             HostIp = ip;
    18         }
    19 
    20         /// <summary>
    21         ///     调用时间,格式:yyyyMMddHH24mmss
    22         /// </summary>
    23         public string CallTime { get; private set; }
    24 
    25         /// <summary>
    26         ///     消息序列号 UUID
    27         /// </summary>
    28         public string SerialNo { get; private set; }
    29 
    30         /// <summary>
    31         ///     客户端IP地址
    32         /// </summary>
    33         public string HostIp { get; private set; }
    34 
    35         /// <summary>
    36         ///     客户端类型:1:pc 2:手机
    37         /// </summary>
    38         public string ClientType { get; private set; }
    39 
    40         /// <summary>
    41         ///     业务信息
    42         /// </summary>
    43         public T Message { get; set; }
    44 
    45     }
    View Code

    测试程序用到的自定义日志类:

     1 public class InsuranceLog
     2     {
     3         /// <summary>
     4         ///     当前登录用户
     5         /// </summary>
     6         public string UserName { get; set; }
     7 
     8         /// <summary>
     9         ///     业务key
    10         /// </summary>
    11         public string BusinessKey { get; set; }
    12 
    13         /// <summary>
    14         ///     业务名称 如:查询政策  下订单  查看订单
    15         /// </summary>
    16         public string BusinessName { get; set; }
    17 
    18         /// <summary>
    19         ///     业务参数
    20         /// </summary>
    21         public string BusinessParameters { get; set; }
    22     }
    View Code

    未完待续

  • 相关阅读:
    spring配置详解
    表单重复提交解决办法
    Java 两个变量交换值
    spring @ExceptionHandler注解方式实现异常统一处理
    mybatis实战
    使用soapui调用webservice接口
    使用火狐的restclient发送http接口post及get请求
    很多网站301重定向
    邮件发布google blogger 博客
    php file取重复
  • 原文地址:https://www.cnblogs.com/autohome7390/p/5443811.html
Copyright © 2020-2023  润新知