【问题标题】:What simple mechanism for synchronous Unix pooled processes?同步 Unix 池进程的简单机制是什么?
【发布时间】:2012-03-17 10:37:05
【问题描述】:

我需要限制并行执行的进程数。例如我想执行这个伪命令行:

export POOL_PARALLELISM=4
for i in `seq 100` ; do
    pool foo -bar &
done

pool foo -bar # would not complete until the first 100 finished.

因此,尽管有 101 个 foos 排队等待运行,但在任何给定时间只有 4 个在运行。 pool 将 fork()/exit() 并将剩余进程排队直到完成。

有没有一种简单的机制可以用 Unix 工具来做到这一点? atbatch 不适用,因为它们通常在每分钟的顶部调用并按顺序执行作业。使用队列不一定是最好的,因为我希望这些是同步的。

在我编写一个使用信号量和共享内存的 C 包装器,然后调试我肯定会介绍的死锁之前,任何人都可以推荐一个 bash/shell 或其他工具机制来完成此任务。

【问题讨论】:

  • 你想要完成什么?您在此处陈述的机制听起来可能不是您可能遇到的问题的正确解决方案。
  • 有某个TCP端口连接饿的程序。当它运行时,它会建立数百个出站连接。它由 HTTP CGI 请求触发。通常不是问题,但如果我可以限制在任何给定时间被调用的这些连接的数量(即使它们阻塞一小段时间),这将有助于管理所述连接(网络管理员讨厌这个应用程序)。
  • 你最好把所说的程序变成一个带有作业队列的事件驱动的单一服务器——它会从根本上降低你的整体负载。谷歌搜索“C10K 问题”,详细了解为什么这是一个常见问题。
  • 您是说对于任何给定的 CGI 请求,您希望最多同时运行四个foo -bar 实例吗?或者您是说在所有 CGI 请求中,您希望最多同时运行四个foo -bar 实例?
  • @ruakh,不是针对每个 CGI 请求,仅针对这个特定的 CGI 程序(它从大量数据源创建图表)。它的数量很少,但是当员工早上来时,他们都会同时出现,并且会产生数千个连接。我不能在 TCP 或 HTTP 级别进行节流,因为这会影响站点的其余部分。所以我想我可以包装这个 CGI 程序并绑定这个 CGI 程序的所有请求中发生多少并发请求(你的后一种情况)

标签: bash unix process queue pool


【解决方案1】:

这个工具肯定没必要自己写,有几个不错的选择。

make

make 可以很容易地做到这一点,但它确实广泛依赖 文件 来驱动这个过程。 (如果您想对生成输出文件的每个输入文件运行一些操作,这可能很棒。)-j 命令行选项将运行指定数量的任务,-l load-average 命令行选项将指定开始新任务之前必须满足的系统负载平均值。 (如果您想“在后台”做一些工作,这可能会很好。不要忘记 nice(1) 命令,它在这里也可以提供帮助。)

所以,快速(且未经测试)Makefile 用于图像转换:

ALL=$(patsubst cimg%.jpg,thumb_cimg%.jpg,$(wildcard *.jpg))

.PHONY: all

all: $(ALL)
        convert $< -resize 100x100 $@

如果您使用make 运行它,它将一次运行一个。如果您使用make -j8 运行,它将运行八个单独的作业。如果您运行make -j,它将启动数百个。 (在编译源代码时,我发现两倍的内核数是一个很好的起点。这让每个处理器在等待磁盘 IO 请求时都有事可做。不同的机器和不同的负载可能会以不同的方式工作。)

xargs

xargs 提供--max-procs 命令行选项。如果可以使用 ascii NUL 分隔的输入命令或换行符分隔的输入命令基于单个输入流来划分并行进程,则这是最好的。 (好吧,-d 选项可以让您选择其他东西,但这两个是常见且简单的。)这使您受益于使用find(1) 强大的文件选择语法,而不是编写像Makefile 这样的有趣表达式上面的示例,或者让您的输入与文件完全无关。 (考虑一下,如果您有一个将大合数分解为素数的程序 - 使该任务适合 make 充其量是很尴尬的。xargs 可以很容易地做到这一点。)

前面的示例可能如下所示:

find . -name '*jpg' -print0 | xargs -0 --max-procs 16 -I {} convert {} --resize 100x100 thumb_{}

parallel

moreutils 软件包(至少在 Ubuntu 上可用)提供了parallel 命令。它可以以两种不同的方式运行:在不同的参数上运行指定的命令,或者并行运行不同的命令。前面的示例可能如下所示:

parallel -i -j 16 convert {} -resize 100x100 thumb_{} -- *.jpg

beanstalkd

beanstalkd 程序采用了完全不同的方法:它提供了一个消息总线供您提交请求,并且作业服务器阻止正在输入的作业,执行作业,然后返回等待队列中的新作业。如果您想将数据写回启动作业的特定 HTTP 请求,这可能不太方便,因为您必须自己提供该机制(可能在 beanstalkd 服务器上提供不同的“管”),但如果最终结果是将数据提交到数据库、电子邮件或类似的异步方式,这可能是最容易集成到现有应用程序中的方法。

【讨论】:

  • 考虑到海报上面解释的问题域,所有这些似乎都是错误的选择。事实上,我认为这些都与海报想要的东西不太相似—— make 和 xargs 特别不合适。
  • @Perry:同意。当任务看起来面向 shell 脚本时,我认为它们是相当合适的。我添加了一个新机制beanstalkd,它提供了一种工作队列方法——它应该更容易集成到大多数“网络应用程序”中。
  • @sarnold - 我没有使用过beanstalkd,但这是减去异步的正确方法,如果不延迟,我需要这种同步(但我会查看配置文档)。如果parallel 可以在调用之间进行协调,那会起作用,但我认为不会?
  • 我建议的前三种机制makexargsparallel 都假设 one 调用是作业请求的完整和全部来源。我认为它们不能很好地转换为 CGI 领域。使用beanstalkd,您可以让您的 CGI 添加新作业,然后坐等在 beantalk 上发送回响应(作为新的“作业请求”),但由您来编写它。 .
猜你喜欢
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 2014-07-25
  • 2010-10-12
  • 2011-01-08
  • 2013-07-20
  • 2010-11-14
  • 1970-01-01
相关资源
最近更新 更多