基础概述 对于log4j2的同步和异步的讲解,本人也是找了很多的资料,也阅读了官方的文档和源码。
对于两者的区别已经发送log执行流程可参考下面的文章,讲的挺全面的:
https://www.cnblogs.com/yeyang/p/7944906.html
其中对于AsyncAppender和AsyncLogger源码的解读可参考:
https://www.cnblogs.com/lewis09/p/10003462.html
https://www.cnblogs.com/lewis09/p/10004117.html
Disruptor详解请参考:
https://www.jianshu.com/p/bad7b4b44e48
配置优化
本文是对之前那篇log4j2异步将log发送到kafka(https://blog.csdn.net/qq_35754073/article/details/103386177)的补充和log4j2在高并发情况下的优化。场景:qps需要可以稳定在10000以上,可是测试到3000就发生qps下降的情况,通过对apm以及服务cpu,内存的分析确认是log4j严重影响了性能,所以有了后来大量寻找log4j2异步性能的一些问题,总结之后也是对项目log4j2做了一些优化,也是的确提升了性能。
1.给log增加tracking_id,对每次请求的log作标识。
2.Loggers的配置从大部分配在root改为配置在logger,因为陪在root发现会有一些不是项目中的log发送到了kafka,而logger就很精准。
3.增加Disruptor队列长度并配置队列堵塞丢弃策略从而增加高并发下的性能
添加tracking_id:
String tracingId = request.getHeader("tracing_id");
if (tracingId == null || tracingId.isEmpty()) {
tracingId = UUID.randomUUID().toString();
}
MDC.put("tracking_id", tracingId);
代码中直接使用:
因为MDC是线程安全的,每个线程都有唯一的一个,所以我们直接使用就可以了
String tracingId = MDC.get(Constant.TRACKING_ID);
【java|log4j2异步详解及高并发下的优化】在log4j2输出log的时候默认输出tracing_id:
Configuration:
Properties:
Property:
- name: log-path
value: "logs"
- name: charset
value: "UTF-8"
- name: log.pattern
value: "%d{yyyy-MM-dd HH:mm:ss.SSS} -%5p ${PID:-} [%X{tracking_id}] [%15.15t] %-30.30C{1.} : %m%n"
Appenders:
Console:
name: CONSOLE
target: SYSTEM_OUT
PatternLayout:
pattern: ${log.pattern}
RollingFile:
- name: REQUEST_LOG
fileName: ${log-path}/request.log
filePattern: "${log-path}/historyLog/info-%d{yyyy-MM-dd}-%i.log.gz"
Filters:
ThresholdFilter:
- level: error
onMatch: DENY
onMismatch: NEUTRAL
- level: warn
onMatch: DENY
onMismatch: NEUTRAL
- level: info
onMatch: ACCEPT
onMismatch: DENY
JsonLayout:
- charset: ${charset}
compact: ${compact}
complete: ${complete}
stacktraceAsString: ${stacktraceAsString}
eventEol: ${eventEol}
properties: true
KeyValuePair:
- key: tags
value: REQUEST_LOG
Policies:
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
DefaultRolloverStrategy:
max: 100
- name: REQUEST_LOG
#下面是输出PatternLayout
#fileName: ${log-path}/request.log
#filePattern: "${log-path}/historyLog/info-%d{yyyy-MM-dd}-%i.log.gz"
#PatternLayout:
#charset: ${charset}
#pattern: ${log.pattern}
#Filters:
#ThresholdFilter:
#- level: error
#onMatch: DENY
#onMismatch: NEUTRAL
#- level: warn
#onMatch: DENY
#onMismatch: NEUTRAL
#- level: debug
#onMatch: ACCEPT
#onMismatch: DENY
#Policies:
#TimeBasedTriggeringPolicy:
#interval: 1
#modulate: true
#DefaultRolloverStrategy:
#max: 100
Loggers:
AsyncRoot:
level: debug
#add location in async
includeLocation: true
AppenderRef:
- ref: CONSOLE
AsyncLogger:
- name: REQUEST_LOG
AppenderRef:
- ref: REQUEST_LOG
Loggers全部改为AsyncLogger:
Loggers:
AsyncRoot:
level: debug
#add location in async
includeLocation: true
AppenderRef:
- ref: CONSOLE
AsyncLogger:
- name: REQUEST_LOG
AppenderRef:
- ref: REQUEST_LOG
- name: SERVICE_LOG
AppenderRef:
- ref: SERVICE_LOG
- name: ERROR_LOG
AppenderRef:
- ref: ERROR_LOG
代码中使用:
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public interface NeuralyzerLog {
Logger requestLog = LogManager.getLogger("REQUEST_LOG");
Logger serviceLog = LogManager.getLogger("SERVICE_LOG");
Logger errorLog = LogManager.getLogger("ERROR_LOG");
}
增加Disruptor队列长度并配置队列堵塞丢弃策略:
需要更改System Property(系统参数)
log4j2.asyncLoggerRingBufferSize:指定队列的长度
log4j2.AsyncQueueFullPolicy:指定堵塞丢弃策略,如果未指定此属性或具有value
"Default"
,则此工厂创建DefaultAsyncQueueFullPolicy
对象。如果此属性具有value "Discard"
,则此工厂将创建 DiscardingAsyncQueueFullPolicy
对象。默认情况下,如果队列已满,此路由器将丢弃级别为INFO,DEBUG和TRACE的事件。可以使用属性log4j2.DiscardThreshold
(开始丢弃的级别名称)进行调整。更详细的参数请参考官网:
https://logging.apache.org/log4j/2.x/manual/async.html
指定System Property(系统参数)的方式:
1.启动参数方式
启动的时候增加-Dlog4j2.asyncLoggerRingBufferSize=123456789
2.log4j2提供的og4j2.component.properties file方式
classpath下创建og4j2.component.properties文件
log4j2.asyncLoggerRingBufferSize=123456789log4j2.AsyncQueueFullPolicy=Discardlog4j2.AsyncQueueFullPolicy=Discard;
log4j2.DiscardThreshold=INFO
如果两者都配置了,则第二种方式将会覆盖第一种方式的配置。
推荐阅读
- Java|Java基础——数组
- 人工智能|干货!人体姿态估计与运动预测
- java简介|Java是什么(Java能用来干什么?)
- Java|规范的打印日志
- Linux|109 个实用 shell 脚本
- 程序员|【高级Java架构师系统学习】毕业一年萌新的Java大厂面经,最新整理
- Spring注解驱动第十讲--@Autowired使用
- SqlServer|sql server的UPDLOCK、HOLDLOCK试验
- jvm|【JVM】JVM08(java内存模型解析[JMM])
- 技术|为参加2021年蓝桥杯Java软件开发大学B组细心整理常见基础知识、搜索和常用算法解析例题(持续更新...)