Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pod 中获取到错误的 CPUS #25

Open
xiaoxiaojx opened this issue Jan 5, 2022 · 5 comments
Open

Pod 中获取到错误的 CPUS #25

xiaoxiaojx opened this issue Jan 5, 2022 · 5 comments
Labels
docker Develop faster. Run anywhere. Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

Comments

@xiaoxiaojx
Copy link
Owner

xiaoxiaojx commented Jan 5, 2022

image

背景

同学 a 在 gitlab CI 上的单测运行失败了, 错误信息如下。于是他按照 jest/issues/8769 的建议,在运行单测的命令上加上了 --maxWorkers=2 的参数,发现不止没有报错了,单测运行的时间还快了 5 倍 ?! 所以询问我这是发生了什么化学反应🤔

  ● Test suite failed to run

    Call retries were exceeded

      at ChildProcessWorker.initialize (../node_modules/jest-worker/build/workers/ChildProcessWorker.js:193:21)

jest --maxWorkers

image

--maxWorkers 参数表示的是 jest 会开启多少个线程去完成所有的测试任务,默认值是 50% * os.cpus().length,相关的文档可见 Jest docs/cli#--maxworker

其实早在之前, 同学 b 就告诉了我,咱们的机器规格很高,比如 xxx 服务就有 96 核。所以我首先打印了一下单测节点的机器的配置,发现有 64 核。那么本次单测线程数就有了 32 个。

分析

我的猜想是 Jest 比如并行跑两个用例时,由于 Node 线程间内存不共享,每个线程中的用例如果 import 了同样的文件都会通过 tsTransform、babelTransform 去转译一次,做了大量的重复工作而导致的耗时严重。

Node 线程的实现可见之前写的一篇文章 【node 源码学习笔记】worker_threads 工作线程 ,另外关于如何提升 Node 线程之间大量数据交换的效率也是我近期一直关注学习的点,后面有机会整理分享一次。

接着我又去咨询运维的大佬,大佬说这里的 64 核是宿主机的,分配给单测节点的可能只有 5核。

那么这样看来, 多线程在需要大量共享数据的情况下会变慢,而现在更是运超了分到的 CPU 资源的 6 倍之多,造成速度如此之缓慢就是情理之中的。

可行的方案

接着我尝试搜索了一下 Node 如何能获取到 k8s 分配到的给容器的资源数量,没有搜索到可直接使用的方案, 仅下面的方案看上去比较接近一点。

该方案是把设置的 resources 参数通过环境变量 MY_CPU_LIMIT 的形式传递给容器,详细可见 Kubernetes 用 Container 字段作为环境变量的值

apiVersion: v1
kind: Pod
metadata:
  name: dapi-envars-resourcefieldref
spec:
  containers:
    - name: test-container
      image: k8s.gcr.io/busybox:1.24
      command: [ "sh", "-c"]
      args:
      - while true; do
          echo -en '\n';
          printenv MY_CPU_REQUEST MY_CPU_LIMIT;
          printenv MY_MEM_REQUEST MY_MEM_LIMIT;
          sleep 10;
        done;
      resources:
        requests:
          memory: "32Mi"
          cpu: "125m"
        limits:
          memory: "64Mi"
          cpu: "250m"
      env:
        - name: MY_CPU_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.cpu
        - name: MY_CPU_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.cpu
        - name: MY_MEM_REQUEST
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: requests.memory
        - name: MY_MEM_LIMIT
          valueFrom:
            resourceFieldRef:
              containerName: test-container
              resource: limits.memory
  restartPolicy: Never

有趣的是本地 Docker 容器中 os.cpus().length 不是宿主机中的核数,而是 Docker Desktop 中 Resources 设置的 CPUS。

image

小结

同理现在的 Node 服务通过集群模式启动直接使用 os.cpus().length 也是有问题的,暂时写死并发的数量去解决。也在 CNode 社区提了一个问答 如何在容器内获取分配到的 cpu 资源数量, 看看有没有踩过坑的大佬有更好的办法 ~

2022-01-29 补充

经过评论区 @Kaijun 大佬指点, 借鉴 Go 的解决方案 https://github.com/uber-go/automaxprocs , 实现了一版 Node.js 方案 https://github.com/xiaoxiaojx/get_cpus_length ,多方测试后是可行的 ✅

@Kaijun
Copy link

Kaijun commented Jan 29, 2022

竟然从zhihu一路过来看到凯多大佬的 blog

go 社区有自动探测 container 内,通过 procfs 找到容器进程 cgroup 的信息,推算出容器自身的 cpu 限制 ,可以参考: https://github.com/uber-go/automaxprocs

node 社区可能没有相关的自适应的工具和包,可以尝试搞一个

@xiaoxiaojx
Copy link
Owner Author

竟然从zhihu一路过来看到凯多大佬的 blog

go 社区有自动探测 container 内,通过 procfs 找到容器进程 cgroup 的信息,推算出容器自身的 cpu 限制 ,可以参考: https://github.com/uber-go/automaxprocs

node 社区可能没有相关的自适应的工具和包,可以尝试搞一个

哈哈,看来是熟人 😁 ,感谢大佬指点,我们再研究一下

@Kaijun
Copy link

Kaijun commented Jan 29, 2022

竟然从zhihu一路过来看到凯多大佬的 blog
go 社区有自动探测 container 内,通过 procfs 找到容器进程 cgroup 的信息,推算出容器自身的 cpu 限制 ,可以参考: https://github.com/uber-go/automaxprocs
node 社区可能没有相关的自适应的工具和包,可以尝试搞一个

哈哈,看来是熟人 😁 ,感谢大佬指点,我们再研究一下

也可以脑壳喊我 @chiji

@snakeUni
Copy link

竟然从zhihu一路过来看到凯多大佬的 blog
go 社区有自动探测 container 内,通过 procfs 找到容器进程 cgroup 的信息,推算出容器自身的 cpu 限制 ,可以参考: https://github.com/uber-go/automaxprocs
node 社区可能没有相关的自适应的工具和包,可以尝试搞一个

哈哈,看来是熟人 😁 ,感谢大佬指点,我们再研究一下

也可以脑壳喊我 @chiji

原来是 chiji

@Kaijun
Copy link

Kaijun commented Jan 30, 2022

竟然从zhihu一路过来看到凯多大佬的 blog
go 社区有自动探测 container 内,通过 procfs 找到容器进程 cgroup 的信息,推算出容器自身的 cpu 限制 ,可以参考: https://github.com/uber-go/automaxprocs
node 社区可能没有相关的自适应的工具和包,可以尝试搞一个

哈哈,看来是熟人 😁 ,感谢大佬指点,我们再研究一下

也可以脑壳喊我 @chiji

原来是 chiji

瞻仰各位大佬们

@xiaoxiaojx xiaoxiaojx added docker Develop faster. Run anywhere. and removed 随笔 labels Sep 15, 2022
@xiaoxiaojx xiaoxiaojx added Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. DEBUG debug and removed DEBUG debug labels Sep 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docker Develop faster. Run anywhere. Node.js Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
Projects
None yet
Development

No branches or pull requests

3 participants