限制 chrome headless CPU 和内存使用

Limit chrome headless CPU and memory usage

我正在使用 selenium 运行 chrome headless 使用以下命令:

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,有人知道我们如何限制 CPU/Memory 使用 chrome headless 吗?或者如果有一些解决方法。

提前致谢。

考虑使用 Docker。它具有对系统资源(如内存和 cpu)的阈值使用情况进行详细记录的功能。好消息是,构建一个 Docker 内部带有无头 Chrome(在 X11 之上)的图像非常容易。

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

关于不可预测的 CPU内存消耗 的讨论很多,作者是 Chrome 无头 会话。

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

  • 使用自定义代理或 C++ ProtocolHandlers,您可以 return 存根 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

  • 不要运行无头浏览器:

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

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

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

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

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

  • page.waitForNavigation:

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

  • 用docker包容一切:

    Chrome 需要很多依赖项才能正确获得 运行ning。即使在所有这些都完成之后,您仍然需要担心诸如字体和幻影进程之类的事情,因此使用某种容器来容纳它是理想的选择。 Docker 几乎是为此任务定制的,因为您可以限制可用资源的数量并将其沙盒化。自己创建 Docker 文件

    并且为了避免运行进入僵尸进程(这通常发生在Chrome),你需要使用像dumb-init[=100这样的东西=] 才能正常启动。

  • 两个不同的运行次:

    可以有两个 JavaScript 运行 次 进行(节点和浏览器)。这对于可共享性的目的来说非常有用,但它的代价是混乱,因为某些页面方法将要求您显式传递引用(与使用闭包或提升相比)。

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

参考:Observations running 2 million headless sessions