現象
spring boot 2.1.6
CentOS 7.4
jdk 1.8
logback 1.2.3
- 一個普通的spring boot項目,在一個磁盤空間相對較小的機器上運行一段時間後總會導致磁盤佔滿
分析
- spring boot使用logback作爲日誌組件,並且有日誌滾動策略,並且日誌滾動策略爲
RollingFileAppender
:最多生成10個日誌文件,每個日誌文件最多10M,理論情況下,日誌應該最多佔用110M空間,實際情況也是如此,因此排除日誌文件寫滿磁盤的原因; - 使用
du -h / --max-depth=1
查看各個根目錄佔用的磁盤空間,發現/var
目錄存在異常:
- 進一步排查發現是
/var/log/message*
佔用較大的磁盤空間:
- 查看任何一個文件,發現內容竟然是spring boot項目的日誌,甚至是已經滾動覆蓋了的日誌;
- 進一步查詢搜索得知,linux系統下的
/var/log/message
是記錄系統服務啓動後產生的日誌的,也就是說spring boot項目是由一個系統服務啓動的,實際情況也正是如此,我們使用systemctl status <jar_pid>找到了啓動該項目的服務文件:
- 是不是說所有使用系統服務啓動的進程,日誌都會保存到
/var/log/message
呢?經過進一步驗證得知,只要進程啓動後不在控制檯輸出日誌,/var/log/message
就不會記錄該進程的日誌,因此猜測spring boot項目除了往日誌文件打印日誌外,應該也向控制檯打印了日誌,查看項目使用的logback.xml後,果真如此:
名稱爲<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <property name="logHome" value="/path/to/log/"/> <property name="maxHistory" value="7"/> <property name="maxFileSize" value="10MB"/> <property name="totalSizeCap" value="200MB"/> <property name="minIndexNum" value="1"/> <property name="maxIndexNum" value="10"/> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] [%p] [%class:%line] %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <appender name="INFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${logHome}/info.log</file> <append>true</append> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> <fileNamePattern>${logHome}/info.%i.log.zip</fileNamePattern> <minIndex>${minIndexNum}</minIndex> <maxIndex>${maxIndexNum}</maxIndex> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>${maxFileSize}</maxFileSize> </triggeringPolicy> <encoder> <pattern>[%d{yyyy-MM-dd HH:mm:ss}] [%thread] [%p] [%class:%line] %msg%n</pattern> <charset>UTF-8</charset> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT"/> <appender-ref ref="INFO"/> </root> </configuration>
STDOUT
的appender即爲輸出日誌到控制檯的配置,註釋掉<appender-ref ref="STDOUT"/>
後,發現項目不再輸出日誌到/var/log/message
原因
可以總結出問題產生的原因:
- 項目由系統服務啓動
- 項目有日誌輸出到控制檯,特別是所有日誌都輸出到控制檯
- 系統日誌沒有排除sprint boot產生的日誌
解決方案
- 對於使用logback.xml的sprint boot項目,問題解決很簡單:直接檢查並禁止控制檯輸出即可,但禁止後會導致本地調試較難,因爲沒有控制檯日誌,可以考慮不同環境使用不同的profile;
- 對於直接使用application.properties配置日誌的項目,可以添加或修改一行配置:
logging.pattern.console=
,沒錯,value爲空,這樣可以阻止spring boot項目輸出日誌到控制檯,但這僅僅是一個hack方法,不是logging.pattern.console
參數的正常表現,甚至是一個BUG,不保證在後續版本中依然生效;
以上兩種解決方案都是在不修改系統配置的情況下,僅改變項目本身的配置或部署流程來解決該問題。
- 同時也可以修改系統日誌配置,比如
CentOS 7
可以修改/etc/rsyslog.conf
(其他發行版本和小版本可能路徑有差異),將/var/log/message
的日誌監聽,排除掉自己的項目,甚至禁止所有日誌輸出到/var/log/message
:/var/log/messages迅速增大的問題