今天下午一半的系統癱瘓了

image

前言

😨不好啦❗ 天塌了❗ 系統崩了❗
😨今天下午,突然一半的系統癱瘓了
無法分配內存:

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),下午就喜提大禮包


原文出處:https://juejin.cn/post/7546054937026183209


共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝8   💬8   ❤️16
409
🥈
我愛JS
📝1   💬6   ❤️4
90
🥉
酷豪
📝1   ❤️1
49
#4
AppleLily
📝1   💬4   ❤️1
37
#5
💬3  
10
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次