天天看点

Tomcat和mysql明明启动了,过一会之后会直接自己杀掉进程,自己取消掉

服务器部署遇到的奇奇怪怪问题:Tomcat和mysql明明启动了,过一会之后会直接自己杀掉进程,自己取消掉

问题解决:

  • 查了springboot项目的日志,没有任何异常信息报错,直接springboot启动到连接数据库的时候,直接停止启动了,这时候

    ps -ef | grep mysql

    ,mysql进程没了…,

    cd /usr/local/mysq/data

    查看mysql的日志,mysql中也没有任何报错信息…
  • 找了整整三天,包括重装Tomcat,重装mysql,还是存在这个问题…
  • 突然在百度时候,看到知乎大佬所说的,

应用部署在线下服务器上,线下服务器,相对来说配置低一些,同时可能和其它的服务部署在一起。后来遇到一个比较怪异的问题:

应用跑一段时间,Tomcat进程就挂掉了。

而且这个没有什么规律,不是在特定操作执行时,或者特定时间出现。同时没有任何的日志。本来以为是其它的服务的人把我们的不小心kill掉了,但kill的有点太频繁了,同时和QA同学了解到,在线下服务器上的其他服务,目前都没有操作过,排除了人为的可能。

剩下的就只能从应用自身的问题入手了。但整个进程挂掉的时候,并没有任何日志生成,同时也没有生成Crash文件。还尝试在启动脚本中增加

-XX:+HeapDumpOnOutOfMemoryError,想要分析下堆内数据,进程退出时也是什么都没生成。

这时就只能请教万能的网络了,Google之后了解到一个Linux OOM Killer。按照这个思路和提供的方式去查看了服务器的日志,果然问题在这儿。

Linux OOM Killer

在这里有一个关于OOM Killer的描述

It is the job of the linux ‘oom killer’ to sacrifice one or more processes in order to free up memory for the system when all else fails. It will also kill any process sharing the same mm_struct as the selected process, for obvious reasons. Any particular process leader may be immunized against the oom killer if the value of its /proc//oomadj is set to the constant OOM_DISABLE (currently defined as -17).

长话短说就是,Linux Kernel的这个Killer,会在内存不足的时候kill掉任何不受保护的进程,从而释放内存,保证Kernel的运行。

要让自己的进程成为一个受保护的进程,请注意这一句:

Any particular process leader may be immunized against the oom killer if the value of its /proc//oomadj is set to the constant OOM_DISABLE (currently defined as -17).

操作方式上可以使用

echo -17 > /proc/$PID/oom_adj

更多可以参考这个网页(OOM Killer - How To Create OOM Exclusions in Linux - Backdrift)

,写一个定时任务,执行脚本,把当前进程的Pid加到这个oomadj里。

那怎么判断进程是不是被OOM Killer给干掉了呢?

可以从/var/log/messages这个文件里查找下,是否有之前pid对应的进程Kill信息,或者进程名,比如我们这里说的是Java应用,就直接查Java的就可以,像

这样的内容,

"Out of memory: Kill process 31201 (java) score 783 or sacrifice child

如果没有这个文件的权限,也可以直接使用如下命令

dmesg | egrep -i ‘killed process’

会有类似这样的输出

Killed process 13090 (java)

知道是被OOM Killer干掉的,那下一步就只能是保证环境的内存够用了,少被其它程序占用,加到受保护进程里,或者直接换个内存充足的服务器吧。 _.

  • 知乎大佬给了灵感啊,然后真的发现tomcat进程和mysql是被系统杀掉的,尝试了大佬说的

    echo -17 > /proc/$PID/oom_adj

    命令,但是因为服务器内存1G本身问题,这样会导致内存溢出报错…
fatal error: runtime: out of memory

runtime stack:
runtime.throw(0x55d9bb6d4f5e, 0x16)
        /usr/local/go/src/runtime/panic.go:774 +0x74 fp=0x7fff5656a668 sp=0x7fff5656a638 pc=0x55d9ba18bb14
runtime.sysMap(0xc000000000, 0x4000000, 0x55d9bd3006d8)
        /usr/local/go/src/runtime/mem_linux.go:169 +0xc7 fp=0x7fff5656a6a8 sp=0x7fff5656a668 pc=0x55d9ba175657
runtime.(*mheap).sysAlloc(0x55d9bd2e7340, 0x2000, 0x0, 0x0)
        /usr/local/go/src/runtime/malloc.go:701 +0x1cf fp=0x7fff5656a750 sp=0x7fff5656a6a8 pc=0x55d9ba16855f
runtime.(*mheap).grow(0x55d9bd2e7340, 0x1, 0xffffffff)
        /usr/local/go/src/runtime/mheap.go:1255 +0xa5 fp=0x7fff5656a7a0 sp=0x7fff5656a750 pc=0x55d9ba1837f5
runtime.(*mheap).allocSpanLocked(0x55d9bd2e7340, 0x1, 0x55d9bd3006e8, 0x1)
        /usr/local/go/src/runtime/mheap.go:1170 +0x268 fp=0x7fff5656a820 sp=0x7fff5656a7a0 pc=0x55d9ba183688
runtime.(*mheap).alloc_m(0x55d9bd2e7340, 0x1, 0x55d9ba1b002a, 0x0)
        /usr/local/go/src/runtime/mheap.go:1022 +0xc6 fp=0x7fff5656a870 sp=0x7fff5656a820 pc=0x55d9ba182f26
runtime.(*mheap).alloc.func1()
        /usr/local/go/src/runtime/mheap.go:1093 +0x4e fp=0x7fff5656a8a8 sp=0x7fff5656a870 pc=0x55d9ba1b50ae
runtime.(*mheap).alloc(0x55d9bd2e7340, 0x1, 0x1002a, 0x40000)
        /usr/local/go/src/runtime/mheap.go:1092 +0x8c fp=0x7fff5656a8f8 sp=0x7fff5656a8a8 pc=0x55d9ba18320c
runtime.(*mcentral).grow(0x55d9bd2e8178, 0x0)
        /usr/local/go/src/runtime/mcentral.go:255 +0x7d fp=0x7fff5656a938 sp=0x7fff5656a8f8 pc=0x55d9ba17507d
runtime.(*mcentral).cacheSpan(0x55d9bd2e8178, 0x7f32461da000)
        /usr/local/go/src/runtime/mcentral.go:106 +0x300 fp=0x7fff5656a998 sp=0x7fff5656a938 pc=0x55d9ba174ba0
runtime.(*mcache).refill(0x7f32461da008, 0x2a)
        /usr/local/go/src/runtime/mcache.go:138 +0x87 fp=0x7fff5656a9b8 sp=0x7fff5656a998 pc=0x55d9ba174637
runtime.(*mcache).nextFree(0x7f32461da008, 0x55d9bd30072a, 0x7f32461da008, 0x8, 0xfffffffffffffff8)
        /usr/local/go/src/runtime/malloc.go:854 +0x89 fp=0x7fff5656a9f0 sp=0x7fff5656a9b8 pc=0x55d9ba168d89
runtime.mallocgc(0x180, 0x55d9bc3452c0, 0x1, 0x55d9bd300740)
        /usr/local/go/src/runtime/malloc.go:1022 +0x7a5 fp=0x7fff5656aa90 sp=0x7fff5656a9f0 pc=0x55d9ba1696d5
runtime.newobject(0x55d9bc3452c0, 0x4000)
        /usr/local/go/src/runtime/malloc.go:1151 +0x3a fp=0x7fff5656aac0 sp=0x7fff5656aa90 pc=0x55d9ba169ada
runtime.malg(0x61c400008000, 0x55d9bd2e99e8)
        /usr/local/go/src/runtime/proc.go:3238 +0x33 fp=0x7fff5656ab00 sp=0x7fff5656aac0 pc=0x55d9ba1950a3
runtime.mpreinit(...)
        /usr/local/go/src/runtime/os_linux.go:324
runtime.mcommoninit(0x55d9bd2e1600)
        /usr/local/go/src/runtime/proc.go:626 +0xc6 fp=0x7fff5656ab38 sp=0x7fff5656ab00 pc=0x55d9ba18e8d6
runtime.schedinit()
        /usr/local/go/src/runtime/proc.go:543 +0x76 fp=0x7fff5656ab90 sp=0x7fff5656ab38 pc=0x55d9ba18e536
runtime.rt0_go(0x7fff5656ac98, 0x3, 0x7fff5656ac98, 0x0, 0x7f324583f6a3, 0x0, 0x7fff5656ac98, 0x300200000, 0x55d9ba1b7400, 0x0, ...)
        /usr/local/go/src/runtime/asm_amd64.s:214 +0x129 fp=0x7fff5656ab98 sp=0x7fff5656ab90 pc=0x55d9ba1b7539
           

因此,不能这样解决…

  • 最终解决方法:

    搜索服务器内存不足解决方法:添加swap交换内存!!

    在CentOS 7上添加Swap交换空间

    最终跟随着大佬的操作添加了1G的swap内存解决了问题~~~

检查系统的Swap信息:swapon -s 
或者free -m
             total       used       free     shared    buffers     cached
Mem:          3953        315       3637          8         11        107
-/+ buffers/cache:        196       3756
Swap:            0          0       4095
           
检查磁盘可用区间:df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        59G  1.5G   55G   3% /
devtmpfs        2.0G     0  2.0G   0% /dev
tmpfs           2.0G     0  2.0G   0% /dev/shm
tmpfs           2.0G  8.3M  2.0G   1% /run
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
这里的-h标记是为了告诉dh将信息输出为对人类友好的格式,比如以MB或GB为单位输出空间使用和空余情况,而不是直接输出内存块的个数。
           
接下来我们将在文件系统上创建swap文件。我们要在根目录(/)下创建一个名叫swapfile的文件,当然你也可以选择你喜欢的文件名。该文件分配的空间将等于我们需要的swap空间。

最快捷的创建方式是fallocate命令,该命令能够创建一个预分配指定大小空间的文件。输入如下指令创建一个4GB的文件:
sudo fallocate -l 4G /swapfile
           
该swap文件将立即创建完毕。我们可以用ls命令检查文件大小:
ls -lh /swapfile


-rw-r--r-- 1 root root 4.0G Oct 30 11:00 /swapfile
           
首先我们需要更改swap文件的权限,确保只有root才可读,否则会有很大的安全隐患。使用chmod命令进行权限操作:
sudo chmod 600 /swapfile
该文件的读写都只有root才能操作。使用ls -lh命令检查一下:
ls -lh /swapfile


-rw------- 1 root root 4.0G Oct 30 11:00 /swapfile
           
使用如下命令告知系统将该文件用于swap:
sudo mkswap /swapfile


Setting up swapspace version 1, size = 4194300 KiB
no label, UUID=b99230bb-21af-47bc-8c37-de41129c39bf
           
这个swap文件就可以作为swap空间使用了。输入如下命令开始使用该swap:
sudo swapon /swapfile
输入如下命令来确认一下设置是否已经生效:
swapon -s


Filename                Type        Size    Used    Priority
/swapfile               file        4194300 0     -1
           
free工具确认:
free -m


             total       used       free     shared    buffers     cached
Mem:          3953        315       3637          8         11        107
-/+ buffers/cache:        196       3756
Swap:         4095          0       4095
           
开机自启:
至此我们已经在系统中启用了swap文件,然而一旦系统重启后,服务器还不能自动启用该文件。要让系统在重启后自动生效swap,我们可以通过修改fstab文件来实现(这是一个管理文件系统和分区的表)。

用sudo权限打开该文件编辑:
sudo vim /etc/fstab
在文件末尾加入下面这行内容,告诉操作系统自动使用刚才创建的swap文件:
/swapfile   swap    swap    sw  0   0
           
这个swap文件就可以作为swap空间使用了。输入如下命令开始使用该swap:
sudo swapon /swapfile
输入如下命令来确认一下设置是否已经生效:
swapon -s


Filename                Type        Size    Used    Priority
/swapfile               file        4194300 0     -1