日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > php >内容正文

php

PHP中使用 fsockopen curl 模拟异步处理

發(fā)布時(shí)間:2023/12/20 php 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP中使用 fsockopen curl 模拟异步处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

PHP它最大缺點(diǎn)就是無法實(shí)現(xiàn)多線程管理,其程序的執(zhí)行都是從頭到尾,按照邏輯一路執(zhí)行下來,不可能出現(xiàn)分支,這一點(diǎn)是限制php在主流程序語言中往更高級的語言發(fā)展的原因之一。

在PHP中我們有的時(shí)候其實(shí)希望在執(zhí)行某項(xiàng)操作的時(shí)候,同時(shí)去執(zhí)行另外一項(xiàng)操作,舉一個場景:在用戶搶票的時(shí)候,你并不希望用戶排隊(duì)去連接數(shù)據(jù)庫進(jìn)行查詢、判斷、插入,完成之后再返回用戶結(jié)果。其實(shí)我們并不需要用戶等那么久的時(shí)間,用戶提交之后,直接告訴他已經(jīng)搶票成功了就可以了,至于各種操作,交給后臺去處理就好。當(dāng)然,這種情況我們現(xiàn)在都用消息列表來處理,把每一個用戶提交的請求存在一個消息列隊(duì)中,告訴用戶已經(jīng)搞定了,用戶愉快的關(guān)掉頁面之后,實(shí)際上后臺還在一個一個從消息列隊(duì)中取出請求進(jìn)行操作。我們這篇文章則是通過一種異類的手法,實(shí)現(xiàn)操作在后臺運(yùn)行,無需用戶等待。今天正好有這個需求。后臺(A服務(wù)器)的操作日志所有記錄在elk系統(tǒng),elk裝在另外一臺服務(wù)器(B)上,打算在B上搭建laravel作為接受日志請求的api
話不多說(方案不是太好,請輕噴哦)

首先,我們要創(chuàng)建一個請求入口:

<?php提交的數(shù)據(jù)(后臺操作行為)提交給后臺API(B服務(wù)器)告訴管理員用戶已經(jīng)搞定了
其次,我們需要一個后臺api處理程序(B服務(wù)器),用戶是否在線并不影響它的運(yùn)行: <?php ignore_user_abort(true); set_time_limit(0);過來的數(shù)據(jù) 數(shù)據(jù)處理

現(xiàn)在的問題是,在第一段代碼中,如何“提交給后臺”?我們通過一種非阻塞式的請求來實(shí)現(xiàn)這個功能。也就是創(chuàng)建一個可以被訪問的url,在這個url運(yùn)行第二段程序,通過一個請求來請求這個url,從而激活第二段程序自動運(yùn)行。接下來我們直接看代碼

比如我的操作后臺(A服務(wù)器):

// 遠(yuǎn)程請求(不獲取內(nèi)容)函數(shù) function _sock($url,$post_data) {$host = parse_url($url,PHP_URL_HOST);$port = parse_url($url,PHP_URL_PORT);$port = $port ? $port : 80;$scheme = parse_url($url,PHP_URL_SCHEME);$path = parse_url($url,PHP_URL_PATH);$query = parse_url($url,PHP_URL_QUERY);if($query) $path .= '?'.$query;if($scheme == 'https') {$host = 'ssl://'.$host;}$method = "GET";if(!empty($post_data)){$method = "POST";}$fp = fsockopen($host,$port,$error_code,$error_msg,1);if(!$fp) {return array('error_code' => $error_code,'error_msg' => $error_msg);}else {stream_set_blocking($fp,false);//如果 mode 為0,資源流將會被轉(zhuǎn)換為非阻塞模式;如果是1,資源流將會被轉(zhuǎn)換為阻塞模式stream_set_timeout($fp,1);//設(shè)置超時(shí)$header = "$method $path HTTP/1.1\r\n";$header.="Host: $host\r\n";foreach($post_data as $k => $v){$_post[]= $k."=".urlencode($v);//必須做url轉(zhuǎn)碼以防模擬post提交的數(shù)據(jù)中有&符而導(dǎo)致post參數(shù)鍵值對紊亂 }$_post = implode('&', $_post);$header .= "Content-Type: application/x-www-form-urlencoded\r\n";//POST數(shù)據(jù)$header .= "Content-Length: ". strlen($_post) ."\r\n";//POST數(shù)據(jù)的長度$header.="Connection: close\r\n\r\n";//長連接關(guān)閉$header .= $_post; //傳遞POST數(shù)據(jù)fwrite($fp, $header);usleep(1000); // 這一句也是關(guān)鍵,如果沒有這延時(shí),可能在nginx服務(wù)器上就無法執(zhí)行成功,網(wǎng)上很多沒有帶這個參數(shù)。反正我?guī)状卧囘^沒有設(shè)置這個是執(zhí)行不了(連接主動斷開時(shí),線上proxy層沒有及時(shí)把請求發(fā)給上游)fclose($fp);return array('error_code' => 0);} } $data = array('authId'=>'authcode','email'=>'zpt@php.net','nickname'=>'周伯通','mailBody'=>'<h3>通哥 <span style="padding:15px">某某的文章</span> 有新的留言</span></h3><p>周某人 < zpt@php.net >在評論中說:</p>' ); echo microtime(),"\r\n"; _sock('http://dev.yiqi.com/Activity/checkdata/cli_fix?m=Comment&a=sendEmail',$data);//dev.yiqihao.com比如是處理請求的api域名(B服務(wù)器),比如laravel構(gòu)建 echo microtime();

我們創(chuàng)建了一個基于fsockopen的函數(shù),這個函數(shù)中利用fsockopen去訪問url,但是在訪問時(shí),并不要求獲取url顯示的內(nèi)容,而是僅僅發(fā)出訪問請求,請求到達(dá)后馬上關(guān)閉這個訪問。這樣做的好處就是無需再等待被訪問的url是否返回了可靠的信息,節(jié)約了時(shí)間,

這段代碼的執(zhí)行時(shí)間在0.1-0.2秒之間,對于普通訪客而言,幾乎察覺不到。因此,在使用時(shí),僅需要調(diào)用這個函數(shù)和對應(yīng)的url即可。不過,這里并沒有提供數(shù)據(jù)傳輸?shù)牟糠?#xff0c;如何傳輸數(shù)據(jù),其實(shí)只需要在$header中增加post的內(nèi)容即可。

接著上面,比如我的B服務(wù)器api :http://dev.yiqi.com/Activity/checkdata/cli_fix 處理簡單的邏輯:

<php echo file_put_contents("test.txt",$_REQUEST, FILE_APPEND);

執(zhí)行_sock后:

除了fsockopen,curl其實(shí)也可以實(shí)現(xiàn)這樣的效果,有些主機(jī)上并不支持fsockopen,我們就可以使用curl來實(shí)現(xiàn)。

function _curl($url) {$ch = curl_init();curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);curl_setopt($ch,CURLOPT_TIMEOUT,1);$result = curl_exec($ch);curl_close($ch);return $result; }

這段代碼的關(guān)鍵是提供了一個Timeout,僅1秒鐘,也就是說curl發(fā)出請求,無論是否接收到返回的內(nèi)容,1秒鐘之后都會關(guān)閉該訪問,因此這個函數(shù)的執(zhí)行數(shù)據(jù)為1.0-1.1秒之間。但對于用戶來說,如果是一個需要進(jìn)行數(shù)據(jù)處理的應(yīng)用,1秒中的等待幾乎是被忽略的,如果你希望用一段更簡單和容易被理解的代碼,可以選擇curl來實(shí)現(xiàn)。這里就不給出示例了。有興趣的朋友可以試著寫一個哦.

總結(jié)

以上是生活随笔為你收集整理的PHP中使用 fsockopen curl 模拟异步处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。