原因

今天一早来到公司,同事说客户反馈生产上的系统数据没有进来了。所以,就排查了下问题才行。

最直接的,先看Tomcat的日志,可以发现到:

Dec 01, 2016 11:01:31 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [ROOT] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused] with root cause
java.net.ConnectException: Connection refused
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:579)

无语,又是RabbitMQ连接不上。

分析crash文件

进入到RabbitMQ,看到有个文件在安装目录下:

-rw-r-----  1 xxx xxx 30908860 Dec  1 09:29 erl_crash.dump

然后接下来就是分析这个crash日志文件了。

分析工具:

github recon erl_crashdump_analyzer

分析

直接执行如何命令即可:

./erl_crashdump_analyzer.sh erl_crash.dump
````

### 输出样本

bash analyzing erl_crash.dump-2016-12-1, generated on: Thu Dec 1 09:28:44 2016

Slogan: eheap_alloc: Cannot allocate 169124672 bytes of memory (of type “heap”).

Memory:

processes: 362 Mb processes_used: 362 Mb system: 181 Mb atom: 0 Mb atom_used: 0 Mb binary: 70 Mb code: 18 Mb ets: 83 Mb


total: 544 Mb

Different message queue lengths (5 largest different):

  1 1
367 0

Error logger queue length:

0

File descriptors open:

UDP: 0 TCP: 10 Files: 77


Total: 87

Number of processes:

368

Processes Heap+Stack memory sizes (words) used in the VM (5 largest different):

  1 24722235
  1 7582861
  2 2072833
  1 1727361
  2 833026

Processes OldHeap memory sizes (words) used in the VM (5 largest different):

  1 28690
  1 10958
  1 6772
  3 4185
  3 2586

Process States when crashing (sum):

  1 Garbing
  1 Scheduled
366 Waiting

导致RabbitMQ crash的原因就在 `Slogan` 这一行里:比如这里,就是因为 ` Cannot allocate 169124672 bytes of memory (of type "heap").` (在堆上分配不到 169124672 bytes 的内存导致崩溃)

### 内存列说明

bash total:当前分配给进程 processes 和系统 system 的内存总量 processes:当前分配给 Erlang 进程的内存总量 processes_used:当前已被 Erlang 进程使用的内存总量(进程内存的一部分) system:当前分配给 Erlang 虚拟机,不过没有被 Erlang 进程占用的内存总量。 atom:当前分配给原子的内存总量(系统进程的一部分) atom_used:当前已被 原子使用的内存总量(系统进程的一部分) binary:当前分配给二进制数据的内存总量(系统进程的一部分) code:当前代码数据所占用的内存总量(系统进程的一部分) ets:当前分配给 ETS 表的内存总量(系统进程的一部分) ```

参考资料

atom binary binary

所有列详解

解决

添加swap分区

发现生产上的系统,根本没有swap分区。如果允许的话,可以添加一个swap分区来进行内存交换到磁盘的缓冲(这个会导致性能下降)

增大内存

因为是使用阿里云,所以,可以动态扩展机器性能

优化程序

尽可能不让MQ堆积太多数据,应该及时处理好出入队的速率