环境:20台服务器的集群,Java jar程序

经过排查发现是磁盘满了,参考之前我的文章
如何排查磁盘100%

发现一个令人大吃一惊的事情,每台机器是40G硬盘,日志文件占了32G,-,-

发现info的日志有几天的info.log文件有2G左右,这谁顶的住,应该是线上出了bug,然后疯狂打日志(内网环境没法复现)。

(解释一下不是我写的…)

至于为什么部分请求成功呢?因为20台还没有所有机器都满。

首先肯定是删除一波日志文件解决问题

删除文件是解决了,但是不可能隔一段时间就上去删一下吧,程序员是不可能干这样的事情的,-。-,

最后肯定是需要定时删除下日志的,要么程序本身定时删除,要么定时脚本删除

(不推荐脚本删除,别人接收你的项目会发现联带的东西很多,很乱,尽量保持程序的专一和简洁,用行话叫 解耦 🎅🏽)

日志解决方案

直接说日志配置解决方案

Configuration:
  Properties:
    Property:
      - name: log.path
        value: /Users/admin/log/lib
      - name: application.name
        value: lib
  Appenders:
    RollingRandomAccessFile:
      - name: infoRollingFile
        ThresholdFilter:
          level: error
          onMatch: DENY
          onMismatch: ACCEPT
        fileName: ${log.path}/info.log
        filePattern: ${log.path}/info.%d{yyyy-MM-dd}.log
        PatternLayout:
          Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
        Policies:
          SizeBasedTriggeringPolicy:
            size: 2M
          TimeBasedTriggeringPolicy:
            interval: 2
            modulate: true
        DefaultRolloverStrategy:
          Delete:
            IfFileName:
              glob: "*log"
            IfLastModified:
              age: 1s
          max: 3
      - name: errorRollingFile
        ThresholdFilter:
          level: error
          onMatch: ACCEPT
          onMismatch: DENY
        fileName: ${log.path}/err.log
        filePattern: ${log.path}/err.%d{yyyy-MM-dd}.log
        PatternLayout:
          Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
        Policies:
          SizeBasedTriggeringPolicy:
            size: 1M
          TimeBasedTriggeringPolicy:
            interval: 1
            modulate: true
        DefaultRolloverStrategy:
          max: 3
          Delete:
            basePath: ${log.path}
            IfFileName:
              glob: "*log"
            IfLastModified:
              age: 1s
    Console:
      name: console
      PatternLayout:
        Pattern: '[%d]\t%p\t[${application.name}]\t%c{1}\t%M\t[%t]\t[%X{reqId}]\t--\t%m%n'
      target: SYSTEM_OUT
  Loggers:
    Root:
      level: info
      AppenderRef:
#        - ref: console
        - ref: infoRollingFile
        - ref: errorRollingFile

上面是我测试使用的日志配置,可以实现过期日志文件自动删除,亲测可以! 但是里面的配置还是要按实际的来

log4j2本身就考虑到日志文件太大的问题,支持日志的限制和过期删除,但是百度的教程大部分是xml文件,是比较旧的教程,而且没有详细讲解参数的具体作用,只给出配置文件。

作为合格的程序员,当然要手动尝试一下,亲测才能推荐出来。(q.q)

	#清除策略
        DefaultRolloverStrategy:
        #删除的触发条件
          Delete:
          #要删除扫描的文件夹
            basePath: ${log.path}
            #限定扫描的文件名
            IfFileName:
            #匹配规则 以log结尾的
              glob: "*log"
              #文件的最新的修改时间间隔
            IfLastModified:
            #1s 表示1秒前  7d表示7天
              age: 1s

1、IfLastModified表示的是最新修改时间,一般是设置为7d,也就是7天,如果你测试日志删除也是配置7d,你会发现删除没有效果,因为你就算新建日志文件,名字取为info.2021-06-02.log也不会删除,因为是你新创建的,修改时间小于7天,所以不执行删除。

2、basePath: ${log.path}必须要,因为没有配置这个属性导致程序不确定你要扫描的文件夹,怕误删文件,所以不执行删除。这个坑是最大的坑,搞到这一步就算是成了。

3、xml配置转化为yml,部分xml教程里面应该是可以真的执行删除的,但是xml配置和yml文件不一样,比如

<DefaultRolloverStrategy max="3">
                <Delete basePath="/Users/admin/log/lib/history" maxDepth="1">
                    <IfFileName glob="*.log.gz"/>
                    <IfLastModified age="3s"/>
                </Delete>
</DefaultRolloverStrategy>

怎么转化为yml文件?又有属性又有子集,其实你把自己想象成开发者就好了,你觉得怎样写yml才和xml文件配置的逻辑一致?

max=3是DefaultRolloverStrategy属性,所以应该是子集

Delete是子集,和属性应该是平级(至少不是max的子集)

最后结论应该是

        DefaultRolloverStrategy:
          max: 3
          Delete:
            basePath: /Users/admin/log/lib/history
            maxDepth: 1
            IfFileName:
              glob: "*.log.gz"
            IfLastModified:
              age: 3s

注意有些可以值可以不加"",但是有些明显是字符串的需要""标记为字符串,
直接写glob: .log.gz 会导致无法识别

4、 IfFileName 也是必要的,不要配置"*.log",因为会删除所有匹配的文件,比如error.log,可以配置为"info*.log"

ok,这样配置一下就可以实现自动删除了,而且你可以本地测试一下,用while打日志,比如你的日志是info.2021-07-02.log名称,那你可以复制一下,名称改为info.2021-06-02.log,然后启动测试类打印日志,你就会发现,满足条件的这个旧的日志自动删除了。

最后附上一个简单的测试类

    @Test
    public void base(){
        StringBuffer buffer=new StringBuffer();
        for (int i=0;i<100;i++){
            buffer.append(i+"hello"+Math.random());
        while (true){
            /*try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            log.info("hello"+buffer.toString());
            //log.error("hello"+Math.random());
https://www.cnblogs.com/xishuai/p/spring-boot-log4j2.html
https://blog.csdn.net/shope9/article/details/87379255
        <dependency>
            <groupId>org.springframew...
                                    <br />在http中Last-Modified 与If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,注意,在这 Last-Modified 是由服务器往客户端发送的 HTTP 头,另一个 If-Modified-Since是由客户端往服务器发送的头,可以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判
                                    日志文件大小1MB,每最多保留10个文件,只保留7日志
rollingRandomAccessFile: # 日志文件Appender,将日志信息输出到日志文件
  - name: ROLLING_FILE
     fileName: ${logPath}/${projectName}.log
     filePattern: "${logPath}/historyLogs/$${date:yyyy-MM}/${projectName}-%d{yyyy-MM-dd}-%i.log.gz"
                                    说明自己翻译官网的说明RollingFileAppenderRollingFileAppender是一个OutputStreamAppender,它(会把日志)写入到filename参数命名的文件中,并且会根据TriggeringPolicy和RolloverPolicy来滚动文件(rolls the file over)。RollingFileAppender会使用RollingFileManag
                                    当log4j使用DailyRollingFileAppender进行日志归档时,需要对日志的个数进行控制。
此时需要对DailyRollingFileAppender进行重写。
package org.apache.log4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
                                    最近做项目的时候,遇到了日志的输出问题。我们想按小时输出日志,同时最多保存7日志。log4j本身自带的appender如下:
org.apache.log4j.ConsoleAppender 输出到控制台
org.apache.log4j.FileAppender 输出到文件
org.apache.log4j.DailyRollingFileAppender 
org.apache.l...
                                    删除过期文件有个坑,好多博文都说删除过期日志文件配置通过max=数字控制.这是不对的这个只是控制某时间段内(根据配置不同)文件的数目.它并不会关心你的目录下一共有多少个日志文件了. 可想而知, 这样随着时间的推移, 虽然每个时间区间内日志数目控制在范围内, 但是, 总日志文件个数, 依然日益膨胀.
正确的应该如下:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterva
implementation 'org.springframework.boot:spring-boot-starter-log4j2'
configurations.all {
        exclude group: 'org.springframework.boot', module: 'spring-boot-s...