php 異步並行

如果你有一批數據需要調用遠程接口處理,而遠程接口處理時間很長,比如需要1秒左右,那10條數據就是10秒,你的程序就要10S才能結束,而這樣的話一旦接口提供方有點問題,就需要20秒 30秒甚至更久,這樣就給我們帶來了極大隱患,雖然我們可以使用設置超時來避免這樣的長久等待,但是如果串行化不解決的話,程序始終是要長時間等所有任務都結束才能繼續判斷後面的結果的。

所以這裏引入異步概念,用  composer require spatie/async 安裝後的 Pool 裏面的create 和 async 以及await來解決問題。

例子如下:

我們接口提供方是這樣的代碼

<?php
sleep(1);
echo json_encode(range(1,15));
exit;

以往我們的調用是這樣的

foreach (range(1, 10) as $v) {
  $list[] = file_get_contents("http://localhost/index.php?act=" . $v);
}

那就是按順序調用接口,統計下來耗時 10021 ms 也就是10秒

現在我們可以這樣做

<?php
include "vendor/autoload.php";

use Spatie\Async\Pool;
$pool = Pool::create();
foreach (range(1, 10) as $item) {
    $pool[] = async(function () use ($item) {
      return file_get_contents("http://localhost/index.php?act=" . $item);
    })->then(function (string $output) use(&$list) {
      $list[] = $output;
    });
}
await($pool);

發現耗時 1341 ms,也就是說基本上是9-10個在同時並行請求,節省了很多時間。

我測試了一下如果不是在循環裏面調用接口,而是簡單的做一個item*2的數學運算,那同步可快多了,異步可慢多了。

<?php
include "vendor/autoload.php";

use Spatie\Async\Pool;
$pool = Pool::create();
foreach (range(1, 10) as $item) {
    $pool[] = async(function () use ($item) {
      return $item * 2;
    })->then(function (string $output) use(&$list) {
      $list[] = $output;
    });
}
await($pool);

耗時 324 ms

而同步的嘛,只要 0.0019 ms

<?php
foreach (range(1, 10) as $v) {
  $list[] = 2 * $v;
}

畢竟這種情況下多餘的異步開銷反而不如同步啊。

適用場景就是多數據量,長耗時任務被阻塞等待,那這個時候用這個東西緩解一下壓力,提高一下速度還是不錯的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章