【发布时间】:2018-09-18 13:16:41
【问题描述】:
我使用 Spring Boot 编写了一个 Java RabbitMQ,并将其容器化为 Docker 容器。当我在我的 MacBook 上运行容器时,它可以很好地使用它的 32 个并发消费者消耗所有排队的消息。但是,当我部署相同的 Docker 映像并在我们的生产服务器上运行它时,它会在一段时间后停止消耗。
上图是它停止的地方。我已将 RabbitMQ 客户端配置为使用 32 个并发消费者,预取计数为 8,这解释了 8 * 32 = 256 条未确认消息。
listener:
simple:
concurrency: 32
max-concurrency: 64
prefetch: 8
retry:
enabled: true
multiplier: 2
max-attempts: 20
stateless: true
initial-interval: 1s
max-interval: 30s
acknowledge-mode: auto
default-requeue-rejected: true
我可以确认 CPU 上绝对没有负载,据我所知,消费者实现不会导致线程等待。我还尝试将启用重试切换为 false 以查看是否有帮助,但没有。
当我在 MacBook 上运行它时,它完全可以正常工作,在这种情况下,我也在本地运行 RabbitMQ 映像。生产服务器在CentOS Linux release 7.4.1708 (Core) 上运行,Docker Java 容器的基础镜像是openjdk:8-jre-alpine。
生产服务器使用--net=host 网络模式在其上托管 RabbitMQ 映像 rabbitmq:3.7-management-alpine 和 Java 容器化应用程序。生产服务器也使用 CSF 防火墙和默认的 HTTP/HTTPS 网络服务器配置进行配置。
我还找到了一个关于服务器上允许的最大打开文件设置的答案,但使用 ulimit 更改硬文件限制也没有任何效果。 Alpine docker 容器的硬文件限制为 1048576,这样就足够了。但在我的 MacBook 上却是 unlimited。
有什么想法吗?
【问题讨论】:
-
检查在 RabbitMQ 管理 UI 中实际注册了多少消费者。如果有消费者,但没有任何反应,请尝试远程调试/分析您的服务以检查线程池。
-
我们曾经遇到过一个非常讨厌的问题,即 OOME 以某种方式使我们的应用程序中的线程消耗为“僵尸”。他们还活着(在 RabbitMQ 中有注册的消费者),但没有做任何事情。我们通过远程分析线程池发现了这一点。不幸的是,我不记得我们究竟是如何做到的,我认为它涉及远程调试或分析。
-
似乎消息正在被传递,并且要么已处理但未确认,要么根本未处理。你能做更多的调试来弄清楚你的消费者发生了什么吗?
标签: java docker spring-boot rabbitmq