我们编写了一个小型C ++应用程序,主要通过ZeroMQ对其他进程进行一些监督。因此,大多数情况下,应用程序处于空闲状态,并定期发送和接收一些请求。
我们基于ubuntu
构建了一个docker映像,该映像仅包含此应用程序,一些依赖项和一个entrypoint.sh
。入口点基本上以/bin/bash
运行,根据环境变量处理一些配置文件,然后通过exec
启动应用程序。
现在这是奇怪的部分。当我们在没有docker的情况下手动启动应用程序时,CPU使用率接近0%。当我们启动与docker image相同的应用程序时,CPU使用率将达到100%,并恰好阻塞了一个CPU内核。
要了解正在发生的情况,我们将图像的入口点设置为/bin/yes
(只是为了确保容器继续运行),然后在正在运行的容器内启动bash。从那里开始,我们手动启动entrypoint.sh
,CPU再次变为0%。
所以我们想知道什么会导致这种情况。我们需要添加到Dockerfile中以防止这种情况吗?
这是strace
生成的一些输出。我用strace -p <pid> -f -c
并等待了五分钟来收集一些见解。
docker run
(100%CPU)下运行strace: Process 12621 attached with 9 threads
strace: [ Process PID=12621 runs in x32 mode. ]
[...]
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
71.26 17.866443 144 124127 nanosleep
14.40 3.610578 55547 65 31 futex
14.07 3.528224 1209 2918 epoll_wait
0.10 0.024760 4127 6 1 restart_syscall
0.10 0.024700 0 66479 poll
0.05 0.011339 4 2902 3 recvfrom
0.02 0.005517 2 2919 write
0.01 0.001685 1 2909 read
0.00 0.000070 70 1 1 connect
0.00 0.000020 20 1 socket
0.00 0.000010 1 18 epoll_ctl
0.00 0.000004 1 6 sendto
0.00 0.000004 1 4 fcntl
0.00 0.000000 0 1 close
0.00 0.000000 0 1 getpeername
0.00 0.000000 0 1 setsockopt
0.00 0.000000 0 1 getsockopt
------ ----------- ----------- --------- --------- ----------------
100.00 25.073354 202359 36 total
docker exec
(0%CPU)运行strace: Process 31394 attached with 9 threads
[...]
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
67.32 12.544007 102 123355 nanosleep
14.94 2.784310 39216 71 33 futex
14.01 2.611210 869 3005 epoll_wait
2.01 0.373797 6 66234 poll
1.15 0.213487 71 2999 recvfrom
0.41 0.076113 15223 5 1 restart_syscall
0.09 0.016295 5 3004 write
0.08 0.014458 5 3004 read
------ ----------- ----------- --------- --------- ----------------
100.00 18.633677 201677 34 total
请注意,在第一种情况下,我早一点开始strace
,所以有一些不同的调用都可以追溯到初始化代码。
我唯一能找到的是使用Process PID=12621 runs in x32 mode.
时的行docker run
。这可能是个问题吗?
还请注意,在两次测量中,过程运行5分钟时,总运行时间约为20秒。
有关100%CPU情况的一些进一步调查。我用top -H -p <pid>
检查了该进程,只有父进程使用100%CPU,而子线程大部分都处于空闲状态。但是当在父进程上调用strace -p <pid>
时,我可以验证该进程没有执行任何操作(不生成任何输出)。
所以我确实有一个进程正在使用我的CPU的整个核心,而完全不执行任何操作。
答案 0 :(得分:1)
事实证明,该软件的某些遗留部分正在等待while循环中的控制台输入:
while (!finished) {
std::cin >> command;
processCommand(command)
}
因此,在本地运行docker exec
时,此方法工作正常。但是由于可执行文件是作为docker服务启动的,因此没有控制台。因此std::cin
是非阻塞的,并立即返回。这样,我们创建了一个无休止的无休止循环,这自然会导致100%的CPU使用率。
感谢@Botje指导我们完成调试过程。