所述HttpRequestPool类提供了一个解决方案.非常感谢那些指出这一点的人.
可以在以下网址找到简要教程:http://www.phptutorial.info/?HttpRequestPool-construct
问题
我想在PHP中进行并发/并行/同时的HTTP请求.我想避免连续请求:
我已经设法找到使用cURL在PHP中制作simultaneousuos [sic] HTTP请求的详细信息,但是如果可能的话,我想明确地使用PHP的HTTP函数.
具体来说,我需要将数据同时发布到一组URL.发布数据的网址超出了我的控制范围; 他们是用户设置的.
我不介意是否需要等待所有请求完成才能处理响应.如果我在每个请求上设置超时30秒并且同时发出请求,我知道我必须等待最多30秒(可能多一点)才能完成所有请求.
我找不到如何实现这一目标的细节.但是,我最近注意到在PHP手册中提到PHP5 +能够处理并发HTTP请求 - 我打算在当时记下它,忘记了,再也找不到它了.
单个请求示例(工作正常)
<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);
$request_1->send();
?>
Run Code Online (Sandbox Code Playgroud)
并发请求示例(不完整,清楚)
<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);
$request_2 = new HttpRequest($url_2, HTTP_METH_POST);
$request_2->setRawPostData($dataSet_2);
// ...
$request_N = new HttpRequest($url_N, HTTP_METH_POST);
$request_N->setRawPostData($dataSet_N);
// Do something to send() all requests at the same time
?>
Run Code Online (Sandbox Code Playgroud)
任何想法都将非常感激!
澄清1:我想坚持PECL HTTP功能:
我公司目前运行第三方仿真程序(自然灾难风险建模),从磁盘上吸取数GB的数据,然后压缩几天以产生结果.我很快就会被要求将其重写为一个多线程应用程序,以便它可以在几小时而不是几天内运行.我希望有大约6个月的时间来完成转换,并将独自工作.
我们有一个24-proc框来运行它.我可以访问原始程序的源代码(我认为用C++编写),但是在这一点上我对它的设计知之甚少.
我需要有关如何解决这个问题的建议.我是一名经验丰富的程序员(约30年,目前在C#3.5工作),但没有多处理器/多线程经验.如果合适的话,我愿意并渴望学习一门新语言.我正在寻找有关语言,学习资源,书籍,建筑指南的建议.等等
要求:Windows操作系统.商业级编译器,提供大量支持和良好的学习资源.不需要花哨的GUI - 它可能从配置文件运行并将结果放入SQL Server数据库.
编辑:当前的应用程序是C++但我几乎肯定不会使用该语言进行重写.我删除了某人添加的C++标记.
我使用Python作为脚本语言来进行数据处理并调用命令行工具进行数字运算.我希望并行运行命令行工具,因为它们彼此独立.当一个命令行工具完成后,我可以从输出文件中收集其结果.所以我还需要一些同步机制来通知我的主Python程序一个任务完成,以便结果可以解析到我的主程序中.
目前,我使用os.system(),它适用于单线程,但不能并行化.
谢谢!
可能重复:
并行处理期间的C#值存储
我今天在我的控制台应用程序中运行了一些性能测试,我偶然发现了一些非常意外的事情.我的代码:
int iterations = 1000000;
var mainList = new List<string>();
for (int i = 0; i < iterations; i++)
{
mainList.Add(i.ToString());
}
var listA = new List<string>();
Parallel.ForEach(mainList, (listItem) =>
{
if (Int32.Parse(listItem)%2 == 0)
{
listA.Add(listItem);
}
});
Console.WriteLine("Parallel Count: {0}", listA.Count);
var listB = new List<string>();
foreach (var listItem in mainList)
{
if (Int32.Parse(listItem) % 2 == 0)
{
listB.Add(listItem);
}
}
Console.WriteLine("Sequential Count: {0}", listB.Count);
Run Code Online (Sandbox Code Playgroud)
这产生了一个输出:
平行计数:495939
顺序计数:500000
我运行了几次,并行循环似乎永远不会在适当的时间执行.任何人都能解释这种"不端行为"吗?并行循环是否值得信赖?
PS我知道在提供的代码示例中有很多废话,比如ToString()调用一个整数而不是解析它们但这只是我在测试时提出的随机代码.提前致谢.
听起来在ZeroMQ中使用传统UNIX套接字的套接字是没有意义的.我基于对ZeroMQ的错误感知设计了一种用于分布式搜索算法的架构.在我的程序中,有一个代理负责监视其他代理并收集他们的数据.在PULL-PUSH或PUB-SUB模式之后,将在代理之间传输实际数据.每个代理都有一个PULL套接字监听传入的消息.每条消息都包含一个ID号,用于指定发送者标识.
在初始化阶段,监视器应该监听其REP套接字.每个代理将连接到监视器的着名REP套接字并自我介绍(发送他的ID号和代理正在侦听的端口号).监视器将有关代理的所有数据存储在三个字段的记录中:<ID, IP, port>.(这是我在ZMQ遇到问题的地方.)当某些代理计数器准备就绪时,监视器会将所有数据(每个代理程序<IP,ID,port>)发送给所有代理程序.最后一步是通过代理和监视器之间的PUB-SUB模式完成的.
这张图片可能有助于了解我的意图:

在上面的图片中,显示器应该将它的表发送给每个人.关键问题是如何以REQ-REP模式获取请求者(任何代理)的公共IP地址?所有代理都绑定到其本地主机(127.0.0.1).它们应该分布在任意数量的主机上.所以AFAIK他们需要了解彼此的公共IP.
在没有解决方案的情况下,任何有关重新设计架构的帮助都是合适的.
更新
我能想到的一个候选解决方案是修改每个代理以绑定到他/她的公共IP而不是localhost.如果有一种获取公共IP地址的神奇方法,任何代理都可以将其地址发送到监视器.
第二次更新
目前,代理获取其公共IP地址并通过消息将其发送到服务器:
std::string AIT::ABT_Socket::getIP() {
std::string address = "";
FILE * fp = popen("ifconfig", "r");
if (fp) {
char *p = NULL, *e;
size_t n;
while ((getline(&p, &n, fp) > 0) && p) {
if (p = strstr(p, "inet addr:")) {
p += 10;
if (e = strchr(p, ' ')) {
*e = '\0';
return std::string(p);
address = std::string(p);
}
}
}
}
pclose(fp);
return …Run Code Online (Sandbox Code Playgroud) 我有一个项目,其中包括一个代码生成器,它只需一次调用代码生成器就可以从一个输入文件生成几个.c和.h文件.我有一个规则,其中.c和.h文件作为多个目标,输入文件作为先决条件,配方是代码生成器的调用.然后我有进一步的规则来编译和链接生成的.c文件.
这可以正常使用-j因子为1,但如果我增加j因子,我发现我得到了代码生成器的多次调用,直到-j因子或预期目标文件的数量,以最小者为准.这很糟糕,因为代码生成器的多次调用可能会因生成的代码被多次写入而导致失败.
我不打算在这里发布我的实际(大)代码,但我已经能够构建一个似乎表现出相同行为的小例子.
Makefile看起来像这样:
output.concat: output5 output4 output3 output2 output1
cat $^ > $@
output1 output2 output3 output4 output5: input
./frob input
clean:
rm -rf output*
对于此示例,我编写了一个简单的shell脚本,frob而不是代码生成器,它从一个输入文件生成多个输出文件:
#!/bin/bash
for i in {1..5}; do
{
echo "This is output${i}, generated from ${1}. input was:"
cat ${1}
} > output${i}
done
当我使用非统一-j因子运行此Makefile时,我得到以下输出:
$ make -j2 ./frob input ./frob input cat output5 output4 output3 output2 output1 > output.concat $
我们看到./frob这里被调用了两次,这很糟糕.有没有什么方法可以构造这个规则,使配方只被调用一次,即使是非统一-j因子?
我考虑过更改规则,以便只有一个预期的输出文件是目标,然后添加另一个没有配方的规则,使其目标是剩余的预期输出文件,先决条件是第一个预期的输出文件.但我不确定这会起作用,因为我不知道我是否可以保证生成文件的顺序,因此可能最终会产生循环依赖.
我有一个非常大的存储磁盘(16T).我想在它上运行'du'来计算每个子目录占用多少.但是,这需要很长时间.幸运的是,我拥有一组计算机.因此,我可以并行运行'du',每个作业都在一个单独的子目录中运行,并编写一个简单的脚本来执行该操作.是否有这样的事情或者我必须自己写吗?
我正在尝试创建一个并行代码来加速处理非常大(几亿行)的数组.为了与此并行化,我将数据切成8个(我的核心数量)碎片,并尝试将每个工人送到1件.然而,看看我的RAM使用情况,似乎每个工件都发送给每个工作人员,有效地将我的RAM使用量乘以8.最小工作示例:
A = 1:16;
for ii = 1:8
data{ii} = A(2*ii-1:2*ii);
end
Run Code Online (Sandbox Code Playgroud)
现在,当我将这些数据发送给使用parfor它的工作人员时,它似乎发送了完整的单元格,而不仅仅是所需的部分:
output = cell(1,8);
parfor ii = 1:8
output{ii} = data{ii};
end
Run Code Online (Sandbox Code Playgroud)
我实际上在parfor循环中使用了一些函数,但这说明了这种情况.MATLAB实际上是将完整的单元格发送data给每个工作人员,如果是这样,如何让它只发送所需的部分?
所以我们有一个不是线程安全的应用程序.它正在使用的一些库正在对文件系统级别进行锁定.不幸的是,它没有正常工作,如果有一些并发使用的库会崩溃并抛出错误.我们也无法切换这个库.要实现并发,哪一个更好?在一台功能强大的机器中运行100个容器或将其分成100个小型机器?
由于我们使用的是亚马逊,我想的是每个运行一个容器的100个X t2.micro实例和一个带有100个泊坞容器的c4.8xlarge机器.我们对记忆没有任何问题.任务受CPU限制.但它也不是那么重,只要它只处理一个t2.micro实例就足以处理它.
我和一位同事讨论了哪一个更好.我更喜欢100个实例,因为我认为Docker隔离将是一个重大的开销.这就像你只有一个资源,但它分为100个需要使用资源的人.另一方面,我的同事提出了一些我认为可能有效的观点.创建Linux命名空间比启动整个操作系统要轻.因此,如果我们有100台机器,我们有100台操作系统,而使用大型机器,我们只有1台操作系统.
问题是,我不知道哪一个是正确的.有这方面知识的人可以解释哪一个会更好并给我一个具体的理由吗?
由于我意识到我刚问了一个不好的问题,我将尝试在这里添加更多信息.为了使问题更加准确,我并不是真的要问哪一个在我的特定用例中更好,哪个更便宜.这只是一个好奇心,在CPU方面表现更好.想象一下,我们有一个非常大的计算问题,我们必须做100个.我们想要并行化它们,但它们不是线程安全的.在100台小型机器或1台100台容器的强大机器中进行它们会更好吗?哪一个会更快完成,为什么?
如果我们只有一台功能强大的机器,那么所有这100个集装箱都不会争夺资源并减缓整个过程吗?如果它是100台小型机器,由于操作系统或其他因素,整体性能可能会更慢?无论如何,我对此没有任何经验.当然我可以试试这个,但最后,因为它不是理想的环境(有很多因素),所以结果不会是权威的.我一直在寻找那些知道两种情况如何在低级别工作的人的答案,并且可以论证哪种环境能够更快地完成任务.
我有一个bash脚本,其函数需要与不同的参数并行运行.我需要知道是否至少有一个执行失败(返回非零) - 无论多少失败都无关紧要.
该命令接受执行的参数数组.由于高负载,我需要将并发限制为4次并发运行.我还需要在父进程(运行bash脚本的进程)中打印日志
这是我正在运行的功能:
function run_and_retry {
EXIT_STATUS=0
$COMMAND || EXIT_STATUS=$?
if [ $EXIT_STATUS -ne 0 ]; then
EXIT_STATUS=0
$COMMAND || EXIT_STATUS=$?
fi
return $EXIT_STATUS
}
Run Code Online (Sandbox Code Playgroud)
我尝试过使用GNU parallel和xargs,并遇到了两个问题.
使用xargs :(无法从中获取退出状态,当我在TravisCI中运行它时也无效)
PARAMETERS=(first-parameter second-parameter third-parameter)
export -f run_and_retry
echo "${PARAMETERS[@]}" | xargs -P 4 -n 1 -I {} bash -c "run_and_retry {}"
Run Code Online (Sandbox Code Playgroud)
使用GNU并行:
PARAMETERS=(first-parameter second-parameter third-parameter)
export -f run_and_retry
parallel -j 4 -k --lb 2 run_and_retry {} ::: echo "${PARAMETERS[@]}"
Run Code Online (Sandbox Code Playgroud) bash ×2
agent ×1
amazon-ec2 ×1
architecture ×1
c# ×1
c++ ×1
command-line ×1
concurrency ×1
csh ×1
docker ×1
du ×1
gnu-make ×1
gnu-parallel ×1
http ×1
linux ×1
makefile ×1
matlab ×1
parfor ×1
pecl ×1
php ×1
python ×1
shell ×1
simulation ×1
simultaneous ×1
spmd ×1
xargs ×1
zeromq ×1