😨不好啦❗ 天塌了❗ 系統崩了❗
😨今天下午,突然一半的系統癱瘓了
無法分配內存:
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00007f1f2adf6000, 12288, 0) failed; error='無法分配內存' (errno=12)
#
# 目前的記憶體不足以讓 Java 運行環境繼續運行。
# 本地內存分配 (mmap) 無法為提交保留的內存映射 12288 位元組。
# 更詳細的錯誤報告文件已保存為:
# /data/online-activity/hs_err_pid2482011.log
遇到這種大面積癱瘓,肯定是立馬執行重啟大法😁
ps aux --sort=-%mem
按照內存使用率降序,查看內存佔用情況:
USER PID %CPU %MEM(佔用率%) VSZ(虛擬內存KB) RSS(物理內存KB) TTY STAT START TIME COMMAND
root 1 0.0 0.0 172328 9520 ? Ss 2317 28:27 /usr/lib/systemd/systemd --switched-root --system --deserialize 18
root 1351641 0.1 0.0 32660 9496 ? Ss 15:12 0:05 sshd: root [priv]
root 1348874 0.0 0.0 32660 9472 ? Ss 14:48 0:00 sshd: root [priv]
root 1348945 0.0 0.0 26400 9468 ? Ss 14:49 0:00 sshd: root [priv]
root 1557164 0.0 0.0 26400 9460 ? Ss 16:05 0:00 sshd: root [priv]
root 1348599 0.0 0.0 26400 9452 ? Ss 14:47 0:00 sshd: root [priv]
root 1419738 0.0 0.0 32660 9428 ? Ss 15:29 0:00 sshd: root [priv]
root 1420875 0.0 0.0 26400 9412 ? Ss 15:30 0:00 sshd: root [priv]
root 1641846 0.6 0.0 22140 8676 pts/9 S+ 16:26 0:00 vim logger.out
上面的情況是事後模擬隨便複製的一個中間信息
發現 vim logger.out
這個命令的進程佔了好幾G的內存。
然後我們第一時間,就殺掉進程:kill -9 1641846
然後重啟所有服務。
📕 第一個日誌生產策略有很大問題!太大了!同時不知道是誰居然用 vim 命令查看了日誌
恢復所有服務之後,需要對內存整體的情況做一個分析以及剩餘大小做一個分析。
執行 free -m
:
‼ 生產環境數據不適合展示,所有隨便調整了一下
total used free shared buff/cache available
Mem: 61551 58489 4910 137 3175 7527
Swap: 0 0 0
下面這個可以方便大家更直觀的了解
內存類型 | 總量(total) | 已使用(used) | 空閒(free) | 可分配給應用(available) |
---|---|---|---|---|
物理內存(Mem) | 61551 | 58489 | 4231 | 6497 |
交換區(Swap) | 0 | 0 | 0 | 0 |
我們的總體內存在幾十個G,剩餘內存在幾個G,因為有些日誌好幾個G了。使用VIM 編輯日誌就直接把日誌加載到內存導致內存佔滿。
❓排查logback-spring.xml 滾動策略,大小限制
看一下日誌的滾動策略,是按月配置了的
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日誌文件輸出的文件名,按月分割,文件名帶起始日期 -->
<FileNamePattern>${LOG_HOME}/${spring.application.name}-%d{yyyy-MM}.log</FileNamePattern>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern>
</encoder>
</appender>
❗發現名稱規則和生產環境的logger.out 也對不上,並且路徑也沒對上。
看了一下啟動命令,才發現問題,所有的日誌都會一直定向的輸入到logger.out中
>>>/app/xx/logger.out &
✔所以不能這麼搞啊,使用logback-spring.xml 配置的策略即可!同時需要排查logback的策略是否有文件大小限制,如下:
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<FileNamePattern>${LOG_HOME}/${spring.application.name}-%d{yyyy-MM-dd}.%i.log</FileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>5GB</totalSizeCap>
<cleanHistoryOnStart>true</cleanHistoryOnStart>
</rollingPolicy>
</appender>
啟動命令存在嚴重的問題,導致把日誌定向輸出到 logger.out
文件中。導致日誌文件日積月累到大幾個G😨
再加上老鐵查看日誌用了不規範的命令,導致大日誌文件加載到內存中,導致內存不足,jvm崩潰。
推薦閱讀:上午系統崩潰(OOM),下午就喜提大禮包