HTML5技术

日交易额百亿级交易系统的超轻量日志实现 - cyfonly(2)

字号+ 作者:H5之家 来源:H5之家 2016-12-10 13:00 我要评论( )

//获得需要进行输出的缓存列表ArrayListStringBuffer alWrtLog = null;synchronized(lfi){ if(lfi.currLogBuff == 'A'){ alWrtLog = lfi.alLogBufA; lfi.currLogBuff = 'B'; }else{ alWrtLog = lfi.alLogBufB; lfi.

//获得需要进行输出的缓存列表 ArrayList<StringBuffer> alWrtLog = null; synchronized(lfi){     if(lfi.currLogBuff == 'A'){         alWrtLog = lfi.alLogBufA;         lfi.currLogBuff = 'B';     }else{         alWrtLog = lfi.alLogBufB;         lfi.currLogBuff = 'A';     }     lfi.currCacheSize = 0; } //创建日志文件 createLogFile(lfi); //输出日志 int iWriteSize = writeToFile(lfi.fullLogFileName,alWrtLog); lfi.currLogSize += iWriteSize;

多刷盘机制

FLogger 支持多种刷盘机制:

下面就来一一分析。

刷盘时间间隔触发

配置项如下:

# 日志写入文件的间隔时间(默认为1000毫秒) WRITE_LOG_INV_TIME = 1000

当距上次刷盘时间超过间隔时间,将执行内存日志刷盘。

内存缓冲大小触发

配置项如下:

# 单个日志文件缓存的大小(默认为10KB) SINGLE_LOG_CACHE_SIZE = 10240

当内存缓冲队列的大小超过配置大小时,将执行内存日志刷盘。

退出强制触发

FLogger 内部注册了 JVM 关闭钩子 ShutdownHook ,当 JVM 正常关闭时,由钩子触发强制刷盘,避免内存日志丢失。相关代码如下:

public FLogger(){     Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {         @Override         public void run() {             close();         }     })); }

当 JVM 异常退出时无法保证内存中的日志全部落盘,但可以通过一种妥协的方式来提高日志刷盘的实时度:设置 SINGLE_LOG_CACHE_SIZE = 0 或者 WRITE_LOG_INV_TIME = 0 。

刷盘代码如下:

/** 线程方法 */ public void run(){     int i = 0 ;     while(bIsRun){         try{             //输出到文件             flush(false);             //重新获取日志级别             if(i++ % 100 == 0){                 Constant.CFG_LOG_LEVEL = CommUtil.getConfigByString("LOG_LEVEL","0,1,2,3,4");                 i = 1;             }         }catch(Exception e){             System.out.println("开启日志服务错误...");             e.printStackTrace();         }     } } /** 关闭方法 */ public void close(){     bIsRun = false;     try{         flush(true);     }catch(Exception e){         System.out.println("关闭日志服务错误...");         e.printStackTrace();     } } /** * 输出缓存的日志到文件 * @param bIsForce 是否强制将缓存中的日志输出到文件 */ private void flush(boolean bIsForce) throws IOException{     long currTime = System.currentTimeMillis();     Iterator<String> iter = logFileMap.keySet().iterator();     while(iter.hasNext()){         LogFileItem lfi = logFileMap.get(iter.next());         if(currTime >= lfi.nextWriteTime || SINGLE_LOG_CACHE_SIZE <= lfi.currCacheSize || bIsForce == true){             //获得需要进行输出的缓存列表             ArrayList<StringBuffer> alWrtLog = null;             synchronized(lfi){                 if(lfi.currLogBuff == 'A'){                     alWrtLog = lfi.alLogBufA;                     lfi.currLogBuff = 'B';                 }else{                     alWrtLog = lfi.alLogBufB;                     lfi.currLogBuff = 'A';                 }                 lfi.currCacheSize = 0;             }             //创建日志文件             createLogFile(lfi);             //输出日志             int iWriteSize = writeToFile(lfi.fullLogFileName,alWrtLog);             lfi.currLogSize += iWriteSize;         }     } }

多 RollingFile 机制

同 log4j/logback,FLogger 也支持多种 RollingFile 机制:

  • 按文件大小 Rolling
  • 按天 Rolling
  • 其中按文件大小 Rolling,配置项为:

    # 单个日志文件的大小(默认为10M) SINGLE_LOG_FILE_SIZE = 10485760

    即当文件大小超过配置大小时,将创建新的文件记录日志,同时重命名旧文件为"日志文件名_日期_时间.log"(如 info_20161208_011105.log)。

    按天 Rolling 即每天产生不同的文件。

    产生的日志文件列表可参考如下:

    info_20161207_101105.log info_20161207_122010.log info_20161208_011110.log info_20161208_015010.log info.log

     当前正在写入的日志文件为 info.log。

    关键代码如下:

    /** * 创建日志文件 * @param lfi */ private void createLogFile(LogFileItem lfi){     //当前系统日期     String currPCDate = TimeUtil.getPCDate('-');     //如果超过单个文件大小,则拆分文件     if(lfi.fullLogFileName != null && lfi.fullLogFileName.length() > 0 && lfi.currLogSize >= LogManager.SINGLE_LOG_FILE_SIZE ){         File oldFile = new File(lfi.fullLogFileName);         if(oldFile.exists()){             String newFileName = Constant.CFG_LOG_PATH + "http://www.cnblogs.com/" + lfi.lastPCDate + "http://www.cnblogs.com/" + lfi.logFileName + "_" + TimeUtil.getPCDate() + "_"+ TimeUtil.getCurrTime() + ".log";             File newFile = new File(newFileName);             boolean flag = oldFile.renameTo(newFile);             System.out.println("日志已自动备份为 " + newFile.getName() + ( flag ? "成功!" : "失败!" ) );             lfi.fullLogFileName = "";             lfi.currLogSize = 0;         }     }     //创建文件     if ( lfi.fullLogFileName == null || lfi.fullLogFileName.length() <= 0 || lfi.lastPCDate.equals(currPCDate) == false ){         String sDir = Constant.CFG_LOG_PATH + "http://www.cnblogs.com/" + currPCDate ;         File file = new File(sDir);         if(file.exists() == false){             file.mkdir();         }         lfi.fullLogFileName = sDir + "http://www.cnblogs.com/" + lfi.logFileName + ".log";         lfi.lastPCDate = currPCDate;         file = new File(lfi.fullLogFileName);         if(file.exists()){             lfi.currLogSize = file.length();         }else{             lfi.currLogSize = 0;         }     } }

    多日志级别

    FLogger 支持多种日志级别:

    FLogger 为每个日志级别都提供了简易 API,在此就不再赘述了。

    打印 error 和 fatal 级别日志时,FLogger 默认会将日志内容输出到控制台。

    热加载

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    网友点评
    l