如果我开始过多的后台工作会怎样?


13

我需要使用Expect脚本在700个网络设备上进行一些工作。我可以按顺序完成它,但是到目前为止,运行时间约为24小时。这主要是由于建立连接所花费的时间以及这些设备(旧设备)的输出延迟。我可以建立两个连接并使它们并行运行,但是我可以推多远呢?

我不认为我可以一次完成所有700个操作,但肯定会有一些限制。我的VM可以管理的telnet连接数量。

如果我确实尝试过像这样的循环来启动其中的700个:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

  • CPU 12个CPU x Intel(R)Xeon(R)CPU E5649 @ 2.53GHz

  • 内存47.94 GB

我的问题是:

  1. 所有700个实例能否同时运行?
  2. 在服务器达到极限之前,我能走多远?
  3. 当达到该限制时,它会只是等待下一次迭代开始foo还是盒子崩溃?

不幸的是,我在公司生产环境中运行,所以我不能完全尝试看看会发生什么。


3
我的运气不错parallel,使用了大约50个并发工作。这是介于1和700之间的并行度的绝佳媒介。另一个不错的是,它是无批次的。单个停止的连接只会停止自身,而不会停止其他任何连接。主要缺点是错误管理。这些基于shell的方法都无法正常处理错误。您必须自己手动检查是否成功,然后重试。
亚当

1
您的任务队列今天可能是700,但是大小可以扩展吗?留意交换空间的增长-这表明您已达到内存限制。而cpu%不是一个好方法(对于linux / unix),最好考虑平均负载(运行队列长度)。
ChuckCottrill

1
我在仍然很新的工作中中断生产的最新方式是一次偶然地运行了一百万个短期工作。他们涉及JVM(等待,等待),因此后果被“限制”在成千上万个无法启动线程的错误报告文件中。
michaelb958--GoFundMonica19年

4
Nitpick:不解析ls输出
l0b0

1
@KuboMD只要没有其他人愿意使用您的代码。
l0b0

Answers:


17

所有700个实例能否同时运行?

这取决于您同时表示的意思。如果我们很挑剔,那么不会,除非您可以在系统上使用700个执行线程(否则可能无法使用),否则它们就不会。但是实际上,是的,只要您在系统上有足够的RAM和/或交换空间,它们就可以。UNIX及其各种子类非常擅长管理大量的并发性,这就是为什么它们在大规模HPC使用中如此受欢迎的部分原因。

在服务器达到极限之前,我能走多远?

没有大量更多信息,这是无法具体回答的。几乎,您需要有足够的内存来满足:

  • 一个作业的整个运行时内存需求乘以700。
  • bash管理这么多作业的内存需求(bash对此并不可怕,但是作业控制并不是完全有效的内存)。
  • 系统上的任何其他内存要求。

假设您遇到了这种情况(同样,只有50GB的RAM,您仍然需要处理其他问题:

  • bash在作业控制上将浪费多少CPU时间?可能不多,但有数百个工作岗位,这可能意义重大。
  • 这将需要多少网络带宽?仅打开所有这些连接可能会淹没您的网络几分钟,具体取决于您的带宽和延迟。
  • 我可能没有想到的许多其他事情。

当达到该限制时,它是否会等待从foo开始下一次迭代,否则盒子会崩溃?

这取决于达到什么极限。如果是内存,则会在系统上死机(更具体地说,是为了释放内存而被内核杀死),或者系统本身可能崩溃(将系统配置为在内存不足时有意崩溃的情况并不少见)。如果是CPU时间,它将一直没有问题,就不可能在系统上做很多其他事情。如果是网络,则可能会使其他系统或服务崩溃。


真正需要的是不要同时运行所有作业。而是将它们拆分为多个批次,并同时运行一个批次中的所有作业,让它们完成,然后开始下一个批次。GNU Parallel(https://www.gnu.org/software/parallel/)可以用于此目的,但是在生产环境中达到这个规模时,它并不理想(如果您愿意,不要太激进,就像我说的那样,您可能会淹没网络并影响系统,否则您将无法接触到)。我真的建议您研究像Ansible(https://www.ansible.com/),因为它不仅可以解决您的并发问题(Ansible会像我上面提到的那样自动进行批处理),而且还为您提供了许多其他有用的功能(例如任务的幂等执行,良好的状态报告以及与之的本机集成)大量其他工具)。


有几种方法可以运行有限数量的后台任务(使用bash,perl,python等),监视任务完成情况以及在先前任务完成时运行更多任务。一种简单的方法是收集由子目录中的文件表示的任务批次,并一次处理一批。还有其他方法……
ChuckCottrill

这还包括类Unix系统吗?什么是“ GUN并行”?
Biswapriyo

2
@ChuckCottrill是的,确实有其他方法可以完成。但是,根据我自己处理此类问题的经验,获得真正的编排工具总比尝试推出自己的解决方案要好得多,尤其是在规模上超过几十个系统之后。
奥斯汀·赫默尔加恩


3
@forest是的,您可以使用rlimits防止系统崩溃,但是在这种情况下使它们正确运行并不容易(您需要事先知道任务的资源要求),并且不能保护这些作业可能造成的任何影响(可能比崩溃本地系统更大的问题)都留在网络的其余部分。
奥斯汀·海默加恩

12

很难具体说明可以按照您描述的方式将多少个实例作为后台作业运行。但是,只要您正确执行操作,一台普通服务器肯定可以维护700个并发连接。网络服务器一直在这样做。

我是否可以建议您使用GNU parallel(https://www.gnu.org/software/parallel/)或类似的方法来完成此操作?这将给您后台作业方法带来许多好处:

  • 您可以轻松更改并发会话数。
  • 它会等到会话完成后再开始新的会话。
  • 它更容易中止。

在这里快速入门:https : //www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source


1
有趣!我来看一下。您知道尝试这种操作(在Parallel的帮助下)是否有使虚拟机管理程序崩溃的风险吗?
KuboMD

2
@KuboMD如果你可以用东西这么世俗崩溃的虚拟机管理程序,它在虚拟机管理程序:)一个错误
霍布斯

顺便说一句,Web服务器经常使用线程或基于事件的处理(例如:gunicorn.org
ChuckCottrill

10

&在进行一些操作以及监视进度时,可以将其用于并行处理。但是,如果您在公司生产环境中运行,则需要可以更好地控制的内容。

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

这将为foo中的每个文件运行~/sagLogs。它每0.5秒启动一个作业,只要有1 GB的可用内存,它将并行运行尽可能多的作业,但是会遵守系统的限制(例如,文件和进程的数量)。通常,这意味着如果您尚未调整允许的打开文件数,则将并行运行250个作业。如果您调整打开文件的数量,只要有足够的内存,并行运行32000应该没有问题。

如果作业失败(即返回错误代码),它将被重试10次。

my.log 会告诉您作业是否成功(可能重试之后)。


这看起来很有希望,谢谢。
KuboMD

运行一个简单的测试cat ~/sagLogs/* >> ~/woah | parallel,然后快速运行。1,054,552行在眨眼之间。
KuboMD

3
您提供的命令具有双重重定向,因此我认为它不会执行您打算执行的操作。GNU Parallel每个作业的开销为10毫秒,因此1M作业应花费3个小时左右。
Ole Tange

1
如果您只想串联文件,则根本不适用。
Ole Tange

1
@KuboMD是一个琐碎的CPU繁忙循环,就像awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' 可以玩耍一样。或尝试执行一项任务,例如sleep 10看到它n无需花费大量CPU时间就能使工作继续进行。例如time parallel sleep ::: {100..1}将睡眠时间从100秒降低到1秒。
彼得·科德斯

1

如果我开始过多的后台工作会怎样?

系统将变得缓慢且无响应,最坏的情况是无响应,最好只按一下电源按钮并进行硬重启...这将作为root用户运行,而它有特权这样做。如果您的bash脚本是在常规用户特权下运行的,那么首先想到的是/etc/security/limits.conf并且/etc/systemd/system.conf[其中的所有变量] [理想地说]可以防止 用户使系统过载

  • cpu =至强E5649,即12 cpu;因此,您有12个核心可同时运行12个进程,每个核心都以100%使用12个核心之一。如果启动24个进程,则每个进程将在12个内核中的每个内核上以50%的利用率运行,700个进程= 1.7%,但这是一台计算机,只要一切能够在适当的时间内正确完成,那么就表示成功。高效并不总是很重要。

    1. 所有700个实例能否同时运行? 当然,700不是一个很大的数字。我的/etc/security/limits.conf maxproc默认为4,135,275

    2. 在服务器达到极限之前,我能走多远? 我敢肯定远远超过700。

    3. 限制 ...如果脚本是在用户帐户下启动的limits.conf,并且脚本通常在尝试执行foo &700次后退出,那么该脚本将在用户帐户下启动(并且通常也适用于所有人)。您可能会希望看到700个foo进程,每个进程使用不同的pid,但您可能只会看到456(随机数选择),而另一个244则从未启动,因为它们被某种安全性或系统限制所阻止。

百万美元的问题:您应同时运行几个?

网络有关,您说每个都将进行telnet连接,有根据的猜测是,在执行cpu和ram限制之前,您将遇到网络限制和开销。但我不知道您在具体做什么,可能会发生的事情是您可以立即启动所有700个设备,但是事情会自动阻塞,直到之前的进程和网络连接根据各种系统限制或类似情况完成并关闭为止。前500个启动,然后其余200个启动,因为系统或内核限制阻止了它。但是,无论一次运行,还是会有一些甜味的可以尽快完成工作……最大限度地减少开销并提高效率。如果是12个核心(如果您有2个cpu,则为24个内核),则立即以12(或24)个内核开始,然后将该并发批号增加12或24,直到看不到运行时间的改善。

提示: google max telnet连接,并查看如何将其应用于您的系统。也不要忘记防火墙。还可以快速计算每个进程所需的内存x 700;确保<可用RAM(在您的情况下约为50gb),否则系统将开始使用SWAP并基本无响应。因此,一次执行12、24,N次启动并监视RAM空闲,然后增加已经知道发生了什么情况的N。

默认情况下,RHEL将单个主机的telnet连接数限制为10个并发会话。这是一项安全功能...设置为10,/ etc / xinetd.conf,更改“ per_source”值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.