如何通过https并行运行多个curl命令

3

我正在尝试使用curl从命令行对运行在本地主机上的服务器进行多个并发请求,但我很难让它们同时运行。实现这一目标的一种简单方法如下:

for ((i = 0; i < 10; i++))
do
  time curl -k https://localhost:$PORT/fooBar &
done

然而,这样做的结果如下:
"my output"
real    0m7.555s
user    0m0.007s
sys     0m0.002s
"my output"
real    0m14.628s
user    0m0.007s
sys     0m0.002s
"my output"
real    0m21.705s
user    0m0.007s
sys     0m0.002s
"my output"
...

尽管该服务器是多线程的且无需锁定(我知道回答者们可能会对此持怀疑态度,但请考虑我尝试的下一个选项),但它仍然存在问题。因为看起来请求是串行的,所以我尝试了以下解决方法:

$ time curl -k https://localhost:$PORT/fooBar &
[1] 6780
$ time curl -k https://localhost:$PORT/fooBar &
[2] 6803
$ curl: (35) Unknown SSL protocol error in connection to localhost:<my port>

real    0m1.030s
user    0m0.003s
sys     0m0.002s
"my output"
real    0m7.128s
user    0m0.007s
sys     0m0.002s

有什么想法可以解释为什么这些请求在使用后台处理的for循环中似乎是串行运行的,以及为什么当我直接从命令行使用后台处理时会出现SSL错误?
编辑:经过进一步研究,发现缺乏并行性是因为服务器正在使用scala spray,并且即使端点的处理程序被标记为“阻塞”,请求也是由单个线程中的actor处理的。这个观察结果将这个问题分成了两部分。与bash和curl相关的一个是for循环和多个shell one-liner产生不同的结果(其中一个导致SSL错误)。解决服务器端的并发问题似乎是一个单独的问题。
不幸的是,我不确定如何普遍地重现这个问题,因为这是一个私有服务器,但我希望有人能够知道为什么for循环和one-liner可能会产生不同的结果。
1个回答

3

仅仅将进程在后台启动听起来很容易,而且非常诱人,但是除非你正在迭代一个小集合,否则最好不要这样做。因为你无法控制并发下载进程的数量,所以可能会占用CPU和/或网络。

我建议使用xargs命令。

CONCURRENT_PROCESSES=10
seq 1 9 | 
     xargs -P ${CONCURRENT_PROCESSES}  \
         --replace time curl -k https://localhost:{}/fooBar 

xargs--replace选项会自动将每个命令调用的参数数目设置为1(-n 1),并将stdin中给定的每个参数替换为{}

如果你想要更复杂的场景(比如记录每个单独请求的时间),你可能需要调用一个包装脚本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接