来源:https://tinyurl.com/y5zbtgsq

阅读本文,你将了解到

  • 日志输出到文件并根据LEVEL级别将日志分类保存到不同文件
  • 通过异步输出日志减少磁盘IO提高性能
  • 异步输出日志的原理

配置文件logback-spring.xml

SpringBoot工程自带logback和slf4j的依赖,所以重点放在编写配置文件上,需要引入什么依赖,日志依赖冲突统统都不需要我们管了。

logback框架会默认加载classpath下命名为logback-spring或logback的配置文件。将所有日志都存储在一个文件中文件大小也随着应用的运行越来越大并且不好排查问题,正确的做法应该是将error日志和其他日志分开,并且不同级别的日志根据时间段进行记录存储。

标签说明

  • <root>标签,必填标签,用来指定最基础的日志输出级别
    • <appender-ref>标签,添加append
  • <appender>标签,通过使用该标签指定日志的收集策略
    • name属性指定appender命名
    • class属性指定输出策略,通常有两种,控制台输出和文件输出,文件输出就是将日志进行一个持久化。ConsoleAppender将日志输出到控制台
  • <filter>标签,通过使用该标签指定过滤策略
    • <level>标签指定过滤的类型
  • <encoder>标签,使用该标签下的标签指定日志输出格式
    • <pattern>标签指定日志输出格式
  • <rollingPolicy>标签指定收集策略,比如基于时间进行收集
    • <fileNamePattern>标签指定生成日志保存地址,通过这样配置已经实现了分类分天手机日志的目标了

logback 高级特性异步输出日志

之前的日志配置方式是基于同步的,每次日志输出到文件都会进行一次磁盘IO。采用异步写日志的方式而不让此次写日志发生磁盘IO,阻塞线程从而造成不必要的性能损耗。异步输出日志的方式很简单,添加一个基于异步写日志的 appender,并指向原先配置的 appender即可

异步输出日志性能测试

既然能提高性能的话,必须进行一次测试比对,同步和异步输出日志性能到底能提升多少倍?

服务器硬件

  • CPU 六核
  • 内存 8G

测试工具

  • Apache Jmeter

同步输出日志

  • 线程数:100
  • Ramp-Up Loop(可以理解为启动线程所用时间) :0
  • 可以理解为100个线程同时启用

测试结果

重点关注指标Throughput【TPS】吞吐量:系统在单位时间内处理请求的数量,在同步输出日志中TPS为44.2/sec

异步输出日志

  • 线程数 100
  • Ramp-Up Loop:0

测试结果

TPS为497.5/sec,性能提升了10多倍!!!

异步日志输出原理

从logback框架下的Logger.info方法开始追踪。一路的方法调用路径如下图所示:

异步输出日志中最关键的就是配置文件中ch.qos.logback.classic包下AsyncAppenderBase类中的append方法,查看该方法的源码:

通过队列情况判断是否需要丢弃日志,不丢弃的话将它放到阻塞队列中,通过查看代码,这个阻塞队列为ArrayBlockingQueueu,默认大小为256,可以通过配置文件进行修改。

Logger.info(…)到append(…)就结束了,只做了将日志塞入到阻塞队列的事,然后继续执行Logger.info(…)下面的语句了。

在AsyncAppenderBase类中定义了一个Worker线程,run方法中的关键部分代码如下:

从阻塞队列中取出一个日志,并调用 AppenderAttachableImpl类中的 appendLoopOnAppenders方法维护一个 Append列表。Worker线程中调用方法过程主要如下图:

最主要的两个方法就是encode和write方法,前一个法方会根据配置文件中encode指定的方式转化为字节码,后一个方法将转化成的字节码写入到文件中去。所以写文件是通过新起一个线程去完成的,主线程将日志扔到阻塞队列中,然后又去做其他事情了。

实例:

<?xml version="1.0" encoding="UTF-8"?>

<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--windows日志文件存储路径,勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="${user.dir}/logs/"/>
<!--mac日志文件存储路径-->
<!--<property name="LOG_HOME" value="/Users/macbook/Documents/logs"/>-->
<!-- 组件标识 -->
<property name="COMPONENT_ID" value="iDataFusion"/>
<!-- 段标识 -->
<property name="SEGMENT_ID" value="custominterface-base"/> <logger name="org.springframework.scheduling">
<level value="info"/>
</logger> <!-- 控制台输出日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}[%line] - %msg%n</pattern>-->
<pattern>%red(%d{yyyy-MM-dd HH:mm:ss.SSS}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{50})[%line] - %cyan(%msg%n)
</pattern>
</layout>
</appender> <appender name="FILE-error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.error.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.error.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>3</MaxHistory>
<!--日志文件最大的大小-->
<maxFileSize>25MB</maxFileSize>
<!-- 所有归档文件的总大小 -->
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${COMPONENT_ID}.${SEGMENT_ID} [%thread] [%logger{50}:%line] %msg%n
</Pattern>
</layout>
</appender> <appender name="FILE-warn" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.warn.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.warn.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<MaxHistory>3</MaxHistory>
<maxFileSize>25MB</maxFileSize>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${COMPONENT_ID}.${SEGMENT_ID} [%thread] [%logger{50}:%line] - %msg%n
</Pattern>
</layout>
</appender> <appender name="FILE-info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.info.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.info.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<MaxHistory>3</MaxHistory>
<maxFileSize>25MB</maxFileSize>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${COMPONENT_ID}.${SEGMENT_ID} [%thread] [%logger{50}:%line] - %msg%n
</Pattern>
</layout>
</appender> <!-- 文件输出日志 (文件大小策略进行文件输出,超过指定大小对文件备份)-->
<appender name="FILE-debug" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<File>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.debug.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${COMPONENT_ID}.${SEGMENT_ID}.debug.%d{yyyy-MM-dd}.%i.log.zip</FileNamePattern>
<MaxHistory>3</MaxHistory>
<maxFileSize>25MB</maxFileSize>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<Pattern>%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX} %level ${COMPONENT_ID}.${SEGMENT_ID} [%thread] [%logger{50}:%line] - %msg%n
</Pattern>
</layout>
</appender> <logger name="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping" level="off"/>
<logger name="springfox.documentation.schema.ModelContextKeyGenerator" level="off"/>
<logger name="springfox.documentation.spring.web.caching.CachingAspect" level="off"/>
<logger name="springfox.documentation.spring.web.OperationsKeyGenerator" level="off"/>
<logger name="springfox.documentation.spring.web.scanners.ApiListingReferenceScanner" level="off"/>
<logger name="springfox.documentation.schema.property.ModelPropertiesKeyGenerator" level="off"/>
<logger name="springfox.documentation.schema.property.BeanPostProcessorChecker" level="off"/> <!--swagger2官方介绍的bug-->
<logger name="io.swagger.models.parameters.AbstractSerializableParameter">
<level value="ERROR"/>
</logger> <!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
<appender-ref ref="FILE-debug"/>
<appender-ref ref="FILE-info"/>
<appender-ref ref="FILE-warn"/>
<appender-ref ref="FILE-error"/>
</root> </configuration>

Logback文件这么配置,TPS提高至少10倍的更多相关文章

  1. Qt使用预编译头文件Using Precompiled Headers(提升10倍以上)

    预编译头文件是被很多编译器用来编译稳定的代码以及将编译好的稳定代码存储在二进制文件中用于提升编译性能.在随后的编译中,编译器将加载存储状态继续编译指定的文件.每一个随后的编译将更快,因为稳定的代码不需 ...

  2. 使用 PyTorch Lightning 将深度学习管道速度提高 10 倍

    ​  前言  本文介绍了如何使用 PyTorch Lightning 构建高效且快速的深度学习管道,主要包括有为什么优化深度学习管道很重要.使用 PyTorch Lightning 加快实验周期的六种 ...

  3. logback.xml常用配置

    一.logback的介绍 Logback是由log4j创始人设计的又一个开源日志组件.logback当前分成三个模块:logback-core,logback- classic和logback-acc ...

  4. SpringBoot使用注解(@value)读取properties(yml)文件中 配置信息

    为了简化读取properties文件中的配置值,spring支持@value注解的方式来获取,这种方式大大简化了项目配置,提高业务中的灵活性. 1. 两种使用方法1)@Value("#{co ...

  5. 日志文件的配置----【logback-spring.xml】

    一.引入相关包 <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-c ...

  6. SpringBoot Logback无法获取配置中心属性

    SpringBoot Logback无法获取配置中心属性 前言 最近在做项目中,需要把项目中的日志信息通过RabbitMQ将规定格式的消息发送到消息队列中,然后ELK系统通过消息队列拿日志并且保存起来 ...

  7. logback学习与配置使用

    Logback介绍 Logback 分为三个模块:Core.Classic 和 Access.Core模块是其他两个模块的基础. Classic模块扩展了core模块. Classic模块相当于log ...

  8. Linux中环境变量文件及配置

    Linux中环境变量文件及配置   一.环境变量文件介绍 转自:http://blog.csdn.net/cscmaker/article/details/7261921 Linux中环境变量包括系统 ...

  9. JPA 不在 persistence.xml 文件中配置每个Entity实体类的2种解决办法

    在Spring 集成 Hibernate 的JPA方式中,需要在persistence配置文件中定义每一个实体类,这样非常地不方便,远哥目前找到了2种方法.   这2种方式都可以实现不用persist ...

随机推荐

  1. 201571030332 扎西平措 《面向对象程序设计Java》第八周学习总结

    <面向对象程序设计Java>第八周学习总结   项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https: ...

  2. 【西北师大-2108Java】第二次作业成绩汇总

    2[西北师大-2108Java]第二次作业成绩汇总 以命令行方式或在Eclipse集成开发环境中编辑.编译.运行第3章示例程序3-1-3-5,结合程序运行结果理解程序代码,每个示例程序从语法.算法两个 ...

  3. day66_10_10,vue项目环境搭建

    一.下载. 首先去官网查看网址. 下载vue环境之前需要先下载node,使用应用商城npm下载,可以将其下载源改成cnpm: """ node ~~ python:nod ...

  4. C++ try catch 示例代码

    #include<iostream> void f1() { throw std::string("error happen"); } void f2() { try ...

  5. 【CSP-SJX 2019】T4 散步

    Description 传送门 Solution 算法1 32pts 枚举每个时刻,并枚举所有发生的时间,暴力进行更新.发现最多只需要枚举到第 \(L\)个时刻,因为是一个环,所以最多到第L个时刻,所 ...

  6. SOA案例分析浅谈

    SOA是英文 Service-Oriented Architecture 三个首字母单词的缩写,中文译为: 面向服务架构 ( SOA), SOA架构与 B/S . C/S 架构是目前最流行三种 Web ...

  7. 第十 构建Web内容的技术

    第十章 构建Web内容的技术 一.HTML HTML(HyperText Markup Language,超文本标记语言)是为了发送Web 上的超文本(Hypertext)而开发的标记语言.超文本是一 ...

  8. Unity Profiler 记录

    版本 Unity 2018.4.6f1 空包 development build 魅蓝 note3 OPPO R9 VIVO x9 华为 P8 青春版 小米 8 SE iphone se Other ...

  9. USACO19JAN Gold题解

    噩梦的回忆.. 上周日在机房打的模拟赛,结果十分惨烈,就最后一题yy出了正解结果玄学的只拿了80 考试结果:0+0+80=80 订正时对着T3打了2hours结果还是90 订正结果:100+100+9 ...

  10. 启动tomcat内存溢出

    在运行项目的过程中,启动tomcat内存溢出.查阅了一些解决办法,总结出来留个笔记. 1.使用Myeclipse2014+tomcat 7 ,在MyEclipse中将项目部署到Tomcat下,启动to ...