【问题标题】:Limit chrome headless CPU and memory usage限制 chrome 无头 CPU 和内存使用
【发布时间】:2021-12-31 14:06:36
【问题描述】:

我正在使用 selenium 通过以下命令无头运行 chrome:

system "LC_ALL=C google-chrome --headless --enable-logging --hide-scrollbars --remote-debugging-port=#{debug_port} --remote-debugging-address=0.0.0.0 --disable-gpu --no-sandbox --ignore-certificate-errors &"

但是,chrome headless 似乎消耗了太多的内存和 cpu,有人知道我们如何限制 chrome headless 的 CPU/内存使用吗?或者,如果有一些解决方法。

提前致谢。

【问题讨论】:

  • 你如何衡量too much memory and cpu?您的 usecase 是否有关于 memory 和 cpu 使用的规范?
  • @DebanjanB 是的,每当用户开始使用 chrome 无头内存并且 cpu 变得非常高时。
  • 在使用 google-chrome-headless 运行 selenium 测试时,我的内存使用量也很大。我的 1501 次测试平均有大约 36GB 的内存。没错,GB!我在 Debian Jessie 下运行 chromedriver 2.42.591071 和 chrome 69。我使用 32 个线程并行运行测试。
  • 在我的例子中,我设法将内存使用量从 36GB 降低到 14GB,因为我在 rspec 中使用了延迟垃圾回收。我把它关掉了,这节省了很多使用量。

标签: selenium google-chrome headless headless-browser google-chrome-headless


【解决方案1】:

关于 Chrome Headless 会话的不可预测的 CPU内存消耗 有很多讨论。

根据Building headless for minimum cpu+mem usage 的讨论,CPU + 内存使用可以通过以下方式优化:

  • 使用自定义代理或 C++ ProtocolHandlers,您可以返回存根 1x1 像素图像,甚至完全阻止它们。
  • Chromium 团队正在努力在生成帧时添加programmatic control。目前 headless chrome 仍在尝试以 60 fps 进行渲染,这相当浪费。许多页面确实需要几帧(可能 10-20 fps)才能正确渲染(由于使用了 requestAnimationFrameanimation triggers),但我们预计可以节省大量 CPU在这里。
  • MemoryInfra 应该可以帮助您确定在您的设置中哪个组件是最大的内存消耗者。
  • 用法可以是:

    $ headless_shell --remote-debugging-port=9222 --trace-startup=*,disabled-by-default-memory-infra http://www.chromium.org
    
  • Chromium 总是会使用尽可能多的资源。如果你想有效地限制它的使用,你应该考虑使用cgroups


上面提到的几点是在生产环境中运行无头浏览器时要适应的一些常见最佳实践:

图:Headless Chrome 的可变资源使用情况

  • 不要运行无头浏览器

    无论如何,如果可能,请不要运行无头浏览器。无头浏览器是不可预测的和饥饿的。几乎所有你可以用浏览器做的事情(除了插入和运行 JavaScript)都可以用简单的 Linux 工具来完成。有些库提供优雅的 Node API,用于通过 HTTP 请求scraping 获取数据(如果这是您的最终目标)。

  • 不要在不需要时运行无头浏览器

    有些用户试图让浏览器保持打开状态,即使在不使用时也是如此,以便它始终可用于连接。虽然这可能是帮助加快会话启动的好策略,但它只会在几个小时后以痛苦告终。这主要是因为浏览器喜欢缓存东西并慢慢消耗更多的内存。每当您不积极使用浏览器时,请关闭它!

  • 与浏览器并行,而不是页面

    我们应该只在绝对必要时运行一个,下一个最佳实践是通过每个浏览器只运行一个会话。虽然通过页面并行工作实际上可以节省一些开销,但如果一个页面崩溃,它可能会导致整个浏览器崩溃。此外,不能保证每个页面都是完全干净的(cookie 和存储可能会泄露)。

  • page.waitForNavigation

    观察到的最常见问题之一是触发页面加载的操作,以及脚本执行的突然中断。这是因为触发pageload 的操作通常会导致后续工作被吞没。为了解决这个问题,您通常必须调用页面加载操作并立即等待下一个页面加载。

  • 使用 docker 来包罗万象

    Chrome 需要大量依赖才能正常运行。即使在所有这些都完成之后,您也需要担心诸如字体和虚拟进程之类的事情,因此使用某种容器来包含它是理想的。 Docker 几乎是为此任务定制的,因为您可以限制可用资源的数量并将其沙箱化。自己创建自己的 Dockerfile

    为了避免遇到僵尸进程(Chrome 通常会发生这种情况),您需要使用 dumb-init 之类的东西来正确启动。

  • 两个不同的运行时

    可能有两个 JavaScript 运行时在运行(Node 和浏览器)。这对于可共享性来说非常有用,但它以混淆为代价,因为某些页面方法会要求您显式传递引用(与闭包或提升相比)。

    例如,在协议的内部深处使用page.evaluate 时,这实际上是stringifies 函数并将其传递给Chrome,所以像闭包和提升这样的东西根本不起作用。如果您需要将一些引用或值传递到评估调用中,只需将它们作为参数附加即可得到正确处理。

参考:Observations running 2 million headless sessions

【讨论】:

  • 您好,先生。所以我不能依赖在生产环境中以无头模式在 Windows 中运行 chromedriver。我可以相信运行“正常”模式吗?我的所有内存都在无头模式下运行了 3 个 chromedriver (8gb) 实例 1 小时。你知道当我通过网络服务器运行 chromedriver 时(所有调用都变成“无窗口”)它是在正常模式还是无头模式下运行?如果我需要同时运行 50 个 chromedriver 实例,你建议我怎么做?
  • @TatianaPerere 粗略的你可以依靠在无头模式的 Windows 中运行 chromedriver。我只是提供了一些见解。
  • 如果我的计算机由于运行 3 个 chromedriver 实例的修改内存溢出而崩溃,我该怎么办?我需要运行更多实例。你觉得我用 docker 能达到更好的效果吗?
  • 我从来没有想到为什么我必须继续使用 Selenium 和 Chromium。如果我能对此投票一百万次,我会的!
【解决方案2】:

考虑使用 Docker。它具有很好的文档记录功能,用于对内存和 cpu 等系统资源的使用进行阈值处理。好消息是,使用无头 Chrome(在 X11 之上)构建 Docker 映像非常容易。

有很多开箱即用的解决方案,请查看:https://hub.docker.com/r/justinribeiro/chrome-headless/

【讨论】:

  • 你不需要使用docker来控制内存和CPU。 cgroups 免费提供此功能,现在随处可见,您可以在 systemd 中轻松使用它们,按服务或应用程序的特定运行。
猜你喜欢
  • 2017-11-20
  • 2016-12-01
  • 2015-04-10
  • 2020-05-08
  • 2011-10-03
  • 1970-01-01
相关资源
最近更新 更多