亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP中如何實現異步非阻塞

發布時間:2021-06-21 17:38:28 來源:億速云 閱讀:407 作者:Leah 欄目:大數據

PHP中如何實現異步非阻塞,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

一、各種實現方法

1、FastCGI的非阻塞方法:fastcgi_finish_request()

在PHP5.3.3版本之后,不管是Nginx還是Apache服務器只要運行在FastCGI模式下,均可使用該方法,官方解釋的作用是沖刷(flush)所有響應的數據給客戶端。
boolean fastcgi_finish_request ( void )
此函數沖刷(flush)所有響應的數據給客戶端并結束請求。 這使得客戶端結束連接后,需要大量時間運行的任務能夠繼續運行。
用法:可以在讀寫大文件、循環更新數據庫等不影響結果的操作之前,執行該函數,把結果返回給客戶端,php會繼續執行下面的邏輯而不影響客戶端的響應時間。

2、fsockopen()+stream_set_blocking()方法:

fsockopen()方法可以打開一個網絡連接或Unxi套接字連接,stream_set_blocking()方法可以為資源流設置非阻塞或者阻塞模式,
使用fsockopen()打開一個網絡連接或者一個Unix套接字連接,再用stream_set_blocking()設置資源成非阻塞模式請求,則該資源請求會是非阻塞的:
bool stream_set_blocking ( resource $stream , int $mode )
注:$mode=0則是非阻塞的,1則是阻塞的模式。
用法:

<?php

$fp = fsockopen('www.oschina.net', 80, $errno, $errstr, 30);

if( !$fp )
{
    die('error fsockopen');
}

// 轉換到非阻塞模式
stream_set_blocking($fp, 0);

$http = "GET /Save.php / HTTP/1.1\r\n";
$http .= "Host: www.oschina.net\r\n";
$http .= "Connection: Close\r\n\r\n";

fwrite($fp, $http);

while (!feof($fp))
{
    echo fgets($fp, 128);
}
fclose($fp);

3、使用cURL執行異步請求:

cURL除了我們通常使用的curl_init來初始化和發送post和get請求之外,還可以使用curl_multi_init()方法來實現異步請求,其原理是使用系統的select這個多路I/O復用機制來異步發送請求。
通常的用法:

<?php
// 創建一對CURL資源
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "www.oschina.net");

curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$output = curl_exec($ch);

echo $output;

異步用法:

<?php
$time = time();

// 創建一對CURL資源
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, "www.oschina.net");
curl_setopt($ch, CURLOPT_HEADER, TRUE);

// 增加2個句柄
$mh = curl_multi_init();
curl_multi_add_handle($mh, $ch);

// 執行批處理句柄
$running= null;

do {
    usleep(10000); // 延遲10000微秒
    curl_multi_exec($mh, $running);
} while ( $running>0 );

// 關閉全部句柄
curl_multi_remove_handle($mh, $ch);
curl_multi_close($mh);

echo "\n total time: ".(time()-$time)."\r";

4、使用Gearman/Swoole等PHP異步擴展或框架

5、使用緩存和隊列
通常復雜的處理邏輯,我們可以將參數推入隊列,如redis或kafka的隊列服務,開啟一個消費進程去處理隊列事務。
如redis服務的list結構,在之前篇章有過說明。

6、使用pcntl_fork()
在PHP4.1.0版本之后都支持了該函數,使用前需要安裝支持pcntl擴展并添加支持。
官方文檔:在當前進程當前位置產生分支(子進程),這個子進程僅PID(進程號) 和PPID(父進程號)與其父進程不同
說明:int pcntl_fork ( void )
成功時,在父進程執行線程內返回產生的子進程的PID,在子進程執行線程內返回0;
失敗時,在父進程上下文返回-1,不會創建子進程,并且會引發一個PHP錯誤。
用法:

<?php

$pid = pcntl_fork();

// 父進程和子進程都會執行下面代碼
if( $pid== -1 )
{
    // 錯誤處理: 創建子進程失敗時返回-1
    die('could not fork');
}
elseif ( $pid )
{
    //父進程會得到子進程號,所以這里是父進程執行的邏輯
    pcntl_wait($status); // 等待子進程中斷,防止子進程成為僵尸進程
    echo '父進程:'.$status;
}
else
{
    // 子進程得到的$pid為0, 所以這里是子進程執行的邏輯
    echo  '子進程';
}

exit();

二、優劣對比

并發IO問題一直是服務器端編程中的技術難題,從最早的同步阻塞直接Fork進程,到Worker進程池/線程池,到現在的異步IO、協程。阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態。現在網絡的日益發展,對響應時間和處理并發的要求越來越高,所以異步非阻塞的需求也越來越多,優點也顯而易見:
1、非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程,能及時返回響應,減少響應時間;
2、高并發,同步阻塞IO模型的并發能力依賴于進程/線程數量,響應時間的下降可以帶來更多的并發能力。

當然,異步非阻塞又存在缺點:
1、啟動大量進程會帶來額外的進程調度消耗。非阻塞模式下,如果大量線程已經返回響應而仍然在執行計算操作,會使CPU利用率不可控的增高;
2、這種模型嚴重依賴進程的數量解決并發問題,一個客戶端連接就需要占用一個進程,工作進程的數量有多少,并發處理能力就有多少。操作系統可以創建的進程數量是有限的;
3、過多的異步和多線程模型會造成編碼困難或線程混亂,如出現大量僵尸進程等。

三、總結

1、一般情況下,我們不贊成用異步回調的方式去做功能開發,傳統的PHP同步方式實現功能和邏輯是最簡單的,也是最佳的方案。像node.js這樣到處callback,只是犧牲可維護性和開發效率;
2、有些時候很適合用異步,比如FTP、聊天服務器,smtp,代理服務器等等此類以通信和讀寫磁盤為主,功能和業務邏輯其次的服務器程序;
3、異步非阻塞和多線程模型推薦:
(1)swoole框架:fpm里,通過swoole_client把url發送到swoole的server,swoole_server天然支持并行請求,把匯總的結果返回到fpm;
這也是當下PHP最火的異步多線程框架,可以了解一下韓天峰的文章:http://rango.swoole.com/
(2)recoil框架:https://github.com/recoilphp/recoil

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

php
AI

含山县| 方城县| 玉山县| 余庆县| 贡觉县| 溆浦县| 安阳县| 邳州市| 巫溪县| 全椒县| 平安县| 柳州市| 西安市| 屯留县| 山东省| 个旧市| 敦煌市| 宜兰县| 凌海市| 招远市| 张家界市| 安陆市| 会昌县| 屯门区| 海淀区| 冀州市| 苍山县| 江永县| 祁东县| 灵宝市| 定陶县| 墨玉县| 安康市| 怀化市| 家居| 宝坻区| 和平县| 乐清市| 曲阳县| 阿克陶县| 苍梧县|