集团主站
欢迎来到成都达内官方网站!达内—美国上市公司 亿元级外企IT培训企业!
成都it培训哪家好
成都it培训哪家好
全国服务监督电话:400-111-8989  |   联系客服   |
当前位置:主页 > 培训课程 > .NET >

成都.NET培训:.NET 超高速高性能写日志

发布者: 成都达内     浏览次数:     发布时间:2017-04-20 17:46:41

本文教你.NET 超高速高性能写日志:...

  本文教你.NET 超高速高性能写日志:

  1、需求

  需求很简单,就是在C#开发中高速写日志。比如在高并发,高流量的地方需要写日志。我们知道程序在操作磁盘时是比较耗时的,所以我们把日志写到磁盘上会有一定的时间耗在上面,这些并不是我们想看到的。

  2、解决方案

  2.1、简单原理说明

  使用列队先缓存到内存,然后我们一直有个线程再从列队中写到磁盘上,这样就可以高速高性能的写日志了。因为速度慢的地方我们分离出来了,也就是说程序在把日志扔给列队后,程序的日志部分就算完成了,后面操作磁盘耗时的部分程序是不需要关心的,由另一个线程操作。

  俗话说,鱼和熊掌不可兼得,这样会有一个问题,就是如果日志已经到列队了这个时候程序崩溃或者电脑断电都会导致日志部分丢失,但是有些地方为了高性能的写日志,是否可以忽略一些情况,请各位根据情况而定。

  2.2、示例图

成都.NET培训

  3、关键代码部分

  这里写日志的部分LZ选用了比较常用的log4net,当然也可以选择其他的日志组件,比如nlog等等。

  3.1、日志至列队部分

  第一步我们首先需要把日志放到列队中,然后才能从列队中写到磁盘上。

成都.NET培训

  _log是log4net日志组件的ILog,其中包含了写日志,判断日志等级等功能,代码开始部分的if判断就是判断等级和现在的日志等级做对比,看是否需要写入列队,这样可以有效的提高日志的性能。

  其中的_que是ConcurrentQueue列队。_mre是ManualResetEvent信号,ManualResetEvent是用来通知线程列队中有新的日志,可以从列队中写入磁盘了。当从列队中写完日志后,重新设置信号,在等待下次有新的日志到来。

  3.2、列队到磁盘

  从列队到磁盘我们需要有一个线程从列队写入磁盘,也就是说我们在程序启动时就要加载这个线程,比如asp.net中就要在global中的Application_Start中加载。

成都.NET培训

成都.NET培训

  3.3、完整代码

  using log4net;

  using log4net.Config;

  using System;

  using System.Collections.Concurrent;

  using System.Collections.Generic;

  using System.IO;

  using System.Linq;

  using System.Text;

  using System.Threading;

  using System.Threading.Tasks;

  namespace Emrys.FlashLog

  {

  public sealed class FlashLogger

  {

  ///

  /// 记录消息Queue

  ///

  private readonly ConcurrentQueue _que;

  ///

  /// 信号

  ///

  private readonly ManualResetEvent _mre;

  ///

  /// 日志

  ///

  private readonly ILog _log;

  ///

  /// 日志

  ///

  private static FlashLogger _flashLog = new FlashLogger();

  private FlashLogger()

  {

  var configFile = new FileInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log4net.config"));

  if (!configFile.Exists)

  {

  throw new Exception("未配置log4net配置文件!");

  }

  // 设置日志配置文件路径

  XmlConfigurator.Configure(configFile);

  _que = new ConcurrentQueue();

  _mre = new ManualResetEvent(false);

  _log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

  }

  ///

  /// 实现单例

  ///

  ///

  public static FlashLogger Instance()

  {

  return _flashLog;

  }

  ///

  /// 另一个线程记录日志,只在程序初始化时调用一次

  ///

  public void Register()

  {

  Thread t = new Thread(new ThreadStart(WriteLog));

  t.IsBackground = false;

  t.Start();

  }

  ///

  /// 从队列中写日志至磁盘

  ///

  private void WriteLog()

  {

  while (true)

  {

  // 等待信号通知

  _mre.WaitOne();

  FlashLogMessage msg;

  // 判断是否有内容需要如磁盘 从列队中获取内容,并删除列队中的内容

  while (_que.Count > 0 && _que.TryDequeue(out msg))

  {

  // 判断日志等级,然后写日志

  switch (msg.Level)

  {

  case FlashLogLevel.Debug:

  _log.Debug(msg.Message, msg.Exception);

  break;

  case FlashLogLevel.Info:

  _log.Info(msg.Message, msg.Exception);

  break;

  case FlashLogLevel.Error:

  _log.Error(msg.Message, msg.Exception);

  break;

  case FlashLogLevel.Warn:

  _log.Warn(msg.Message, msg.Exception);

  break;

  case FlashLogLevel.Fatal:

  _log.Fatal(msg.Message, msg.Exception);

  break;

  }

  }

  // 重新设置信号

  _mre.Reset();

  Thread.Sleep(1);

  }

  }

  ///

  /// 写日志

  ///

  /// 日志文本

  /// 等级

  /// Exception

  public void EnqueueMessage(string message, FlashLogLevel level, Exception ex = null)

  {

  if ((level == FlashLogLevel.Debug && _log.IsDebugEnabled)

  || (level == FlashLogLevel.Error && _log.IsErrorEnabled)

  || (level == FlashLogLevel.Fatal && _log.IsFatalEnabled)

  || (level == FlashLogLevel.Info && _log.IsInfoEnabled)

  || (level == FlashLogLevel.Warn && _log.IsWarnEnabled))

  {

  _que.Enqueue(new FlashLogMessage

  {

  Message = "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss,fff") + "]\r\n" + message,

  Level = level,

  Exception = ex

  });

  // 通知线程往磁盘中写日志

  _mre.Set();

  }

  }

  public static void Debug(string msg, Exception ex = null)

  {

  Instance().EnqueueMessage(msg, FlashLogLevel.Debug, ex);

  }

  public static void Error(string msg, Exception ex = null)

  {

  Instance().EnqueueMessage(msg, FlashLogLevel.Error, ex);

  }

  public static void Fatal(string msg, Exception ex = null)

  {

  Instance().EnqueueMessage(msg, FlashLogLevel.Fatal, ex);

  }

  public static void Info(string msg, Exception ex = null)

  {

  Instance().EnqueueMessage(msg, FlashLogLevel.Info, ex);

  }

  public static void Warn(string msg, Exception ex = null)

  {

  Instance().EnqueueMessage(msg, FlashLogLevel.Warn, ex);

  }

  }

  ///

  /// 日志等级

  ///

  public enum FlashLogLevel

  {

  Debug,

  Info,

  Error,

  Warn,

  Fatal

  }

  ///

  /// 日志内容

  ///

  public class FlashLogMessage

  {

  public string Message { get; set; }

  public FlashLogLevel Level { get; set; }

  public Exception Exception { get; set; }

  }

  }

  4、性能对比和应用

  4.1、性能对比

  经过测试发现

  使用原始的log4net写入日志100000条数据需要:19104毫秒。

  同样数据使用列队方式只需要251毫秒。

成都.NET培训

  4.2、应用

  4.2.1、需要在程序启动时注册,如asp.net 程序中在Global.asax中的Application_Start注册。

成都.NET培训

  4.2.2、在需要写入日志的地方直接调用FlashLogger的静态方法即可。

  成都.NET培训

  5、代码开源

  https://github.com/Emrys5/Emrys.FlashLog

  成都it培训哪家好,当然是成都达内培训,成都达内是一家专业的程序员培训机构,专注于成都嵌入式培训,成都web前端培训,成都.NET培训,成都大数据培训,成都会计实操培训,成都IT培训,成都编程培训等IT培训,专业的成都软件培训机构,专业师资授课,真实项目实战、零首付、低押金、名企就业。

(责任编辑:成都达内)
最新开班
  • 成都Java培训班
    免费试听名额发放中...
  • 成都C++培训班
    免费试听名额发放中...
  • 成都PHP培训班
    免费试听名额发放中...
  • 成都网络工程培训班
    免费试听名额发放中...
  • 成都Unity3D培训班
    免费试听名额发放中...
  • 成都大数据培训班
    免费试听名额发放中...
  • 成都uid培训班
    免费试听名额发放中...
  • 成都会计培训班
    免费试听名额发放中...
  • 成都Python培训班
    免费试听名额发放中...
  • 成都嵌入式培训班
    免费试听名额发放中...
  • 成都web培训班
    免费试听名额发放中...
  • 成都软件测试培训班
    免费试听名额发放中...
在线留言
提交

校区地址:成都市锦江区东大街紫东楼端35号明宇金融广场19楼1906室

联系电话:400-111-8989

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市高新区奥克斯广场蜀锦路209号一楼商铺

联系电话:400-111-8989

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都锦江区东大街芷泉街229号东方广场C座3楼303

联系电话:400-111-8989

公交路线:芷泉街(188路;115路;515路;236路;505路;501路;84路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市武侯区佳灵路3号红牌楼广场2号写字楼11楼1115号

联系电话:400-111-8989

公交路线:红牌楼东(11路;92路;100路;111路;139路;g28路;快速公交K1/K2) 地铁路线:红牌楼站(地铁3号线)

校区地址:成都市锦江区红星路二段70号四川日报大厦502-2

联系电话:400-111-8989

公交路线:市二医院站(6路;49路;102路;5路;37路;g92路;) 地铁路线:地铁市二医院(地铁3号线)

校区地址:成都市锦江区东大街芷泉段229号东方广场C座16层

联系电话:400-111-8989

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:四川省成都市武侯区高新科技孵化园9号园区E座7楼

联系电话:400-111-8989

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

了解达内动态
关注成都达内教育公众号

首页 | 关于达内 | 课程中心 | 专家师资 | 视频教程 | 学员空间 | 校企合作 | 新闻资讯 | 就业指导 | 网站地图

2016-2025 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56 蜀ICP备18021046号-3