我们编写了一个小型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/

10-16 18:19