原因

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

最直接的,先看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 的内存导致崩溃)

内存列说明

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堆积太多数据,应该及时处理好出入队的速率