SizeAndTimeBasedRollingPolicy支持按大小和时间双维度滚动、自动压缩及过期清理,必须配置fileNamePattern(含%d和%i)、maxFileSize、maxHistory、totalSizeCap四项;%i用于同日多分片,缺一则降级或报错;清理在滚动时触发,满足maxHistory天数或totalSizeCap上限任一条件即执行。

Logback 的 SizeAndTimeBasedRollingPolicy 可以同时按文件大小和时间滚动日志,并支持自动压缩(gzip)和过期删除,是生产环境最常用的滚动策略之一。关键在于正确配置 fileNamePattern、maxFileSize、maxHistory 和 totalSizeCap 四个参数,缺一不可。
核心配置项说明
以下是最小可用且符合生产要求的配置片段(logback.xml 中):
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 滚动后文件名格式,必须含 %d 和 %i -->
<fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<!-- 单个日志文件最大体积 -->
<maxFileSize>100MB</maxFileSize>
<!-- 保留最近 30 天的日志(含所有分片)-->
<maxHistory>30</maxHistory>
<!-- 所有归档日志总大小上限,超出时按时间删除旧文件 -->
<totalSizeCap>5GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
注意:fileNamePattern 必须同时包含日期占位符(如 %d{yyyy-MM-dd})和索引占位符(%i),否则 Logback 会降级为纯时间滚动,丢失按大小切分能力。
为什么必须带 %i?
当单日日志量超过 maxFileSize 时,Logback 会为同一天生成多个文件,例如:
立即学习“Java免费学习笔记(深入)”;
app.2024-06-01.0.gzapp.2024-06-01.1.gzapp.2024-06-01.2.gz
没有 %i 就无法区分同一日期下的多个分片,会导致覆盖或滚动异常。Logback 要求该模式中至少有一个整数转换器(%i),否则启动时抛出 IllegalArgumentException。
过期清理的触发逻辑
Logback 在每次日志滚动(即新文件创建)时检查并执行清理,依据是三个阈值的**交集条件**:
- 文件最后修改时间早于
maxHistory天 → 删除 - 归档总大小超过
totalSizeCap→ 从最旧文件开始删,直到满足上限 - 两个条件独立生效,优先满足任意一个即触发删除
例如:设 maxHistory=30、totalSizeCap=5GB,某天磁盘突增导致总大小达 6GB,则即使部分文件才 25 天,也会被提前清理;反之,若总大小始终未超限,但某文件已满 31 天,仍会被删。
常见踩坑点
-
路径权限问题:确保 Java 进程对
logs/目录有读写权限,否则压缩失败(.gz 文件不生成)且不报错 -
未启用压缩:仅靠
.gz后缀不够,需确认 JVM 能加载java.util.zip.GZIPOutputStream(JDK 自带,一般无问题) - maxHistory 单位是“天”,不是“文件数”:它按文件名中的日期解析,与实际文件数量无关
- 首次启动时不会立即清理:清理只在滚动发生时触发,所以刚上线需等第一次 rollover(比如第二天零点或第一个 100MB 写满)


















