我使用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
。
生产服务器使用rabbitmq:3.7-management-alpine
网络模式在其上托管RabbitMQ映像--net=host
和Java容器化应用程序。还使用具有默认HTTP / HTTPS Web服务器配置的CSF防火墙配置生产服务器。
我还找到了答案,指的是服务器上允许的最大打开文件设置,但使用ulimit
更改硬文件限制也没有任何效果。 Alpine docker容器的硬文件限制为1048576,因此应该足够了。在我的MacBook上,它是unlimited
。
有什么想法吗?
答案 0 :(得分:0)
事实证明问题不是由于RabbitMQ的内部工作,网络或文件描述符限制所致。
在使用SSH本地端口转发进行一些远程调试之后,证明在Docker容器内调用了SecureRandom.getInstanceStrong()
罪魁祸首。显然,这无限期地阻止,没有进一步指示发生了什么。将其更改为new SecureRandom()
会使问题消失。
这是我的Dockerfile
进一步表明我的随机性来源:
FROM openjdk:8-jre-alpine
VOLUME /tmp
ADD libs/app-0.1.0.jar app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-agentlib:jdwp=transport=dt_socket,server=y,address=8000,suspend=n", "-jar", "/app.jar"]
我认为使用SecureRandom.getInstanceStrong()
会绕过urandom
的使用并恢复为random
,从而表现出阻止行为。关于/dev/./random
和/dev/./urandom
之间差异的一些更有趣的读物可以在这里找到:http://www.thezonemanager.com/2015/07/whats-so-special-about-devurandom.html