說明
1. 在 Server 程序中如果需要執行很耗時的操作,比如一個聊天服務器發送廣播,Web 服務器中發送郵件。如果直接去執行這些函數就會阻塞當前進程,導致服務器響應變慢。
Swoole 提供了異步任務處理的功能,可以投遞一個異步任務到 TaskWorker
進程池中執行,不影響當前請求的處理速度。(官網說明)
1. 服務端代碼
執行服務端監聽端口9501
。通過設置daemonize
這個參數,以守護進程在系統去維護這個TaskWorker
進程池。我們客戶端將消息傳遞給服務端,服務端異步將數據請求放入進程池隊列運行,從大大縮短了響應時間。
<?php
/**
* Created by PhpStorm
* User: pl
* Date: 2020/4/26
* Time: 10:29
*/
class TaskServers
{
private $server;
public function __construct()
{
$this->server = new Swoole\Server('127.0.0.1',9501);
$this->server->set([
'task_worker_num' => 3, //開啓的進程數 一般爲cup核數 1-4倍
'daemonize' => 1, //已守護進程執行該程序
'max_request' => 10000, //worker進程最大任務數
'dispatch_mode' => 2, //設置爲爭搶模式
'task_ipc_mode' => 3, //設置爲消息隊列模式
]);
$this->server->on('Receive',array($this,'onReceive'));
$this->server->on('Task',array($this,'onTask'));
$this->server->on('Finish',array($this,'onFinish'));
$this->server->start();
}
/**
* @param swoole_server $server
* @param $fd
* @param $form_id
* @param $data
* 開始投遞異步任務
*/
public function onReceive(swoole_server $server , $fd , $form_id , $data)
{
$this->server->task($data);
}
/**
* @param swoole_server $server
* @param $fd
* @param $from_id
* @param $data
* 執行異步任務
*/
public function onTask( $server , $fd , $from_id , $data)
{
$data = json_decode($data,true);
try {
$log_txt = date('Y-m-d H:i:s')."開始執行任務".PHP_EOL ;
$this->log($log_txt);
return $this->request_curl($data['url'],$data['data'],'post');
}catch (\Exception $exception){
$log_txt = date('Y-m-d H:i:s')."執行任務失敗發生錯誤".PHP_EOL ;
$this->log($log_txt);
}
}
public function onFinish( $server , $task_id, $data)
{
$log_txt = date('Y-m-d H:i:s')."$data".PHP_EOL ;
$this->log($log_txt);
}
public function request_curl($url = '', $request_data = '', $request_type = 'get', $headers = [], $is_ssl = false)
{
$ch = curl_init (); //curl初始化
if( $request_type == 'get' && !empty( $request_data) )
{
$num = 0;
foreach ( $request_data as $key => $value )
{
if($num == 0)
{
$url .= '?' . $key.'='.$value;
}
else{
$url .= '&'. $key . '=' . $value;
}
$num ++;
}
$num = 0;
}
//區分get和post
curl_setopt ( $ch, CURLOPT_URL, $url ); //URL地址
curl_setopt ( $ch, CURLOPT_HEADER, 0 ); //頭信息不輸出
//如果成功只將結果返回,不自動輸出任何內容
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
//post類型就實現此結果
if( $request_type == 'post')
{
//設置爲POST方式
curl_setopt ( $ch, CURLOPT_POST, 1 );
//POST數據
curl_setopt ( $ch, CURLOPT_POSTFIELDS, $request_data );
//當post數據大於1024時強制執行
curl_setopt ( $ch, CURLOPT_HTTPHEADER, array("Expect:"));
}
//判斷是否繞過證書
if( $is_ssl )
{
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//繞過ssl驗證
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
if(!empty($headers)) curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec ( $ch ); //執行
if ( $result == FALSE) return false;
curl_close ( $ch ); //關閉資源
return $result;
}
public function log($log_txt)
{
$log ='log/'.date('Y_m_d').'log';
if(!file_exists($log)) {
touch($log);
chown($log,0777);
}
$file_log = fopen($log,"a");
fputs($file_log,$log_txt);
fclose($file_log);
}
}
$task = new TaskServers();
2. 客戶端代碼
<?php
/**
* Created by PhpStorm
* User: pl
* Date: 2020/4/26
* Time: 11:54
*/
class ClientRequest
{
private $client;
private $params; //請求參數
public function __construct($params)
{
$this->client = new swoole_client(SWOOLE_SOCK_TCP | SWOOLE_KEEP);
$this->params = $params;
}
public function connect()
{
if (!$this->client->connect('127.0.0.1', 9501, 1)) {
return json_encode([
'code' => 500,
'err_msg' => '鏈接異步客戶端失敗'
]);
}
/**
* 注意請求格式
* $params['url'] 接口地址
* $params['type']接口請求方式
* $params['data']參數
*/
$params = $this->params;
$array['url'] = $params['url'];
unset($params['url']);
$array['data'] = $params;
$this->client->send(json_encode($array, JSON_UNESCAPED_UNICODE));
}
}
if (!empty($_GET)) {
$params = $_GET;
}
if (!empty($_POST)) {
$params = $_POST;
}
$client = new ClientRequest($params);
$client->connect();
開始執行服務端程序,php TaskServer.php
我們以接口形式上去調用另外一個耗時接口。簡單對比一下響應速度。
更多學習內容請訪問:
騰訊T3-T4標準精品PHP架構師教程目錄大全,只要你看完保證薪資上升一個臺階(持續更新)
以上內容希望幫助到大家,很多PHPer在進階的時候總會遇到一些問題和瓶頸,業務代碼寫多了沒有方向感,不知道該從那裏入手去提升,對此我整理了一些資料,包括但不限於:分佈式架構、高可擴展、高性能、高併發、服務器性能調優、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql優化、shell腳本、Docker、微服務、Nginx等多個知識點高級進階乾貨需要的可以免費分享給大家,需要的可以加入我的官方羣點擊此處。