最近,MQ经常有丢包的现象,看各connection/channel/consumer/queue的组成情况,发现差别比较大。
channel与消费者:
[root@iZ23nn1p4mjZ bin]# rabbitmqctl list_channels vhost name consumer_count
Listing channels ...
101.69.255.190:45389 -> 120.27.140.42:5672 (1) 0
101.69.255.190:45390 -> 120.27.140.42:5672 (1) 2
101.69.255.190:53602 -> 120.27.140.42:5672 (1) 0
101.69.255.190:53603 -> 120.27.140.42:5672 (1) 3
101.69.255.190:53604 -> 120.27.140.42:5672 (1) 0
101.69.255.190:53605 -> 120.27.140.42:5672 (1) 2
101.69.255.190:53608 -> 120.27.140.42:5672 (1) 0
101.69.255.190:53611 -> 120.27.140.42:5672 (1) 2
101.69.255.190:61824 -> 120.27.140.42:5672 (1) 0
127.0.0.1:42309 -> 127.0.0.1:5672 (2) 72
127.0.0.1:42310 -> 127.0.0.1:5672 (1) 72
127.0.0.1:42310 -> 127.0.0.1:5672 (2) 72
127.0.0.1:42311 -> 127.0.0.1:5672 (1) 72
127.0.0.1:42311 -> 127.0.0.1:5672 (2) 72
127.0.0.1:42313 -> 127.0.0.1:5672 (1) 1
127.0.0.1:43096 -> 127.0.0.1:5672 (1) 0
127.0.0.1:43532 -> 127.0.0.1:5672 (1) 0
127.0.0.1:44215 -> 127.0.0.1:5672 (7) 0
127.0.0.1:44215 -> 127.0.0.1:5672 (8) 0
127.0.0.1:44215 -> 127.0.0.1:5672 (9) 0
127.0.0.1:44297 -> 127.0.0.1:5672 (1) 843
127.0.0.1:44298 -> 127.0.0.1:5672 (1) 843
127.0.0.1:44307 -> 127.0.0.1:5672 (1) 1
找到客户端进程:
[root@iZ23nn1p4mjZ bin]# lsof -i:44297
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
java 7302 root 103u IPv4 783500 0t0 TCP localhost:44297->localhost:amqp (ESTABLISHED)
beam.smp 24260 rabbitmq 45u IPv4 783501 0t0 TCP localhost:amqp->localhost:44297 (ESTABLISHED)
队列与消费者关系:
[root@iZ23nn1p4mjZ bin]# rabbitmqctl list_queues name consumers | more
Listing queues ...
12619352_7172_0_000c29abfef6 1
4654456_6284_0_000c29abfef6 1
AnalyseQuote 0
actL.1.1 2
actL.1.13 2
actL.1.14 2
actL.1.15 2
actL.1.16 2
actL.1.17 2
actL.1.18 2
actL.1.19 2
actL.1.2 2
actL.1.20 2
sysL.4.5 2
sysL.4.6 2
sysL.4.7 2
sysL.4.8 2
sysL.4.9 2
trdL.1.1 8
trdL.1.10 8
trdL.1.11 8
trdL.1.12 8
trdL.1.13 8
trdL.1.14 8
trdL.1.15 8
trdL.1.16 8
trdL.1.17 8
一般来说,consumer和channel是一对一的关系比较好,因为每个channel都有独立的dispatcher线程,这样consumer之间不存在相互blocking和线程安全性问题。
管理通道和连接的线程和Consumers回调线程是独立的线程,所以不用启动专门的线程池去执行业务代码应该也可以可行的,不然的话,就涉及到消息消费无序的问题,这属于消息队列架构设计并发粒度的问题了,应该来说跟业务代码本身无关。另外,channel是非线程安全的,所以如果自己的线程池执行业务逻辑的话,要注意channel可能被同时传递给多个channel的问题。