我们编写了一个小型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
并等待了五分钟以收集一些见解。
1.使用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
2.使用虚拟入口点和
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
行。这可能是个问题吗?还要注意,在两次测量中,过程运行五分钟时,总运行时间约为20秒。
关于100%CPU情况的一些进一步调查。我使用
top -H -p <pid>
检查了该进程,只有父进程使用100%CPU,而子线程全都处于空闲状态。但是,当在父进程上调用strace -p <pid>
时,我可以验证该进程没有执行任何操作(不生成任何输出)。因此,我确实有一个进程正在使用我的CPU的整个内核,而完全不执行任何操作。
最佳答案
事实证明,该软件的一些遗留部分在while循环中等待控制台输入:
while (!finished) {
std::cin >> command;
processCommand(command)
}
因此,这在本地运行并与
docker exec
一起运行时效果很好。但是由于可执行文件是作为docker服务启动的,因此没有控制台。因此,std::cin
是非阻塞的,并立即返回。这样,我们创建了一个无休止的无休止循环,自然会导致100%的CPU使用率。感谢@Botje指导我们完成调试过程。
关于c++ - 通过入口点启动时,用于Docker容器的100%CPU,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57303696/