1. 程式人生 > >PHP並行程式設計探索之二(curl_multi函式組)

PHP並行程式設計探索之二(curl_multi函式組)

      使用pcntl擴充套件實現的多程序終究只能執行在命令列模式,而我們接觸的基本上都處在http請求模式下,那就真沒有解決辦法了麼,有人說用curl,自身請求自身,好我們用curl看一下是不是有用:

       為方便訪問和除錯,我使用的是CI框架,直接在控制器裡操作。

1. 使用curl

(1) 首先我們新增一個耗時計算函式

function microtime_float()
    {
        list($usec, $sec) = explode(" ", microtime());
        return ((float)$usec + (float)$sec);
    }

(2) 然後直接使用Welcome.php 下的Welcome 控制器
class Welcome extends CI_Controller 
{

	public function index()
    { 
        $url = 'http://web.iyy.com/welcome/task?task_id=';
        $start=microtime_float();	
        $len = 2;
        for($i=0;$i<$len; $i++){
            $this->curl($url.$i);
        }       
        $end=microtime_float();
        echo "\n",$end-$start;
    }
    
    public function curl($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }
    
    public function task()
    {
        $task_id = $_REQUEST['task_id'];
        if($task_id == 0){
            sleep(2);  //模擬任務執行時間 2s
            echo '2222'."\n";
        }else{
            sleep(3); //模擬任務執行時間 3s
            echo '3333'."\n";
        }
    }
}

這個例子裡,我們做了一個迴圈請求curl,然後使用引數控制請求的任務,使用sleep模擬任務耗時,最終執行結果如下:


根據執行結果,我們看到,curl並沒有給我們什麼實質性的改變,仍然花費了5s多完成。

2. 使用curl_multi函式組

(1)  引入curl_multi封裝類

class MultiCurl
{
    /*@var array $config*/
    private $config = array();
    /*@var string $baseUrl*/
    private $baseUrl = '';
    /**
     * @todo: 設定基礎路徑
     */
    public function setBaseUrl($url = '')
    {
        $this->baseUrl = $url;
        return $this;
    }
    /**
     * @todo: 設定配置引數
     */
    public function setConfig($config = array())
    {
        $baseUrl = $this->baseUrl ? $this->baseUrl : '';
        foreach($config as $val){
            $this->config[] = array(
                'url' => $baseUrl . $val['url']
            );
        }
        return $this;
    }
    /**
     * @todo: 獲取查詢結果
     */
    public function getRes()
    {
        //2.加入子curl 
        $ch_arr= array();
        $mh = curl_multi_init();
        foreach($this->config as $k=>$val){
        	$ch_arr[$k] = curl_init();
        	curl_setopt($ch_arr[$k], CURLOPT_URL, $val['url']);
        	if(isset($ch_arr[$k]['configs'])){
        		foreach($ch_arr[$k]['configs'] as $kconfig => $config){
        		    curl_setopt($ch_arr[$k], $kconfig, $config);	
        		}
        	}
            curl_setopt($ch_arr[$k], CURLOPT_HEADER, 0);
        	curl_multi_add_handle($mh,$ch_arr[$k]);
        }
        //3.執行curl
        $active = null;
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) == -1) {
                usleep(100);
            }
            do {
                $mrc = curl_multi_exec($mh, $active);
            } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        }
        //4.關閉子curl
        foreach($ch_arr as $val){
            curl_multi_remove_handle($mh, $val);
        }
        //5.關閉父curl
        curl_multi_close($mh);
        //6.獲取執行結果
        foreach($ch_arr as $val){
        	$response[] = curl_multi_getcontent($val);
        }
        return $response;
    }
}


(2) 更改welcome控制器

class Welcome extends CI_Controller 
{

	public function index()
    {
        $start=microtime_float();
        $multicurl = new MultiCurl();
        $baseurl = 'http://web.iyy.com';
        $curl_configs = array(
            array('url'=> '/welcome/task?task_id=0'),
            array('url'=> '/welcome/task?task_id=1')
        );
        $res = $multicurl->setBaseUrl($baseurl)->setConfig($curl_configs)->getRes();
        $end=microtime_float();
        echo "\n",$end-$start;
    }
    
    public function task()
    {
        $task_id = $_REQUEST['task_id'];
        if($task_id == 0){
            sleep(2);  //模擬任務執行時間 2s
            echo '2222'."\n";
        }else{
            sleep(3); //模擬任務執行時間 3s
            echo '3333'."\n";
        }
    }
}

這裡我們使用了curl_multi函式組,同樣的使用curl請求,我們看返回的結果:


看來兩個任務都執行完了,但是基本上,只耗費了最長任務需要的時間,並不是兩個任務的總時間,符合我們並行程式設計的需求,但是話又說回來了,如果我們

併發量很大的前提下,每個請求同時發起兩個或者更多的請求,那負載就又上來了,速度是提上來了,訪問極限量卻變小了,所以這個方案,只能適合訪問數不多,但是要考慮訪問效率的網站

相關推薦

PHP並行程式設計探索(curl_multi函式)

      使用pcntl擴充套件實現的多程序終究只能執行在命令列模式,而我們接觸的基本上都處在http請求模式下,那就真沒有解決辦法了麼,有人說用curl,自身請求自身,好我們用curl看一下是不是有用:        為方便訪問和除錯,我使用的是CI框架,直接在控制器裡

PHP並行程式設計探索三(定時非同步)

       我們或多或少聽過非同步這個詞,這個詞在前端javascrtipt程式設計中很常見,就是對於定時的或ajax請求任務,我們 不用等待,直接執行接下來的程式碼,直到之前的資料有返回。 我們來看個栗子: console.log(new Date()); setTi

Spark程式設計指南:向Spark運算元傳遞函式

文章目錄 向Spark運算元傳遞函式 Java的兩種方法 匿名內部類 建立類實現Function介面 Scala的兩種方法 傳遞匿名函式 定義全域性單例物件中的靜態方法

php數據結構叉樹

http 二叉樹的鏡像 深度 子節點 adding tde ctu tool 恢復 樹是一種比較重要的數據結構, 尤其是二叉樹。二叉樹是一種特殊的樹,在二叉樹中每個節點最多有兩個子節點,一般稱為左子節點和右子節點(或左孩子和右孩子),並且二叉樹的子樹有左右之 分,其次序不能

在Docker中執行PHP專案的探索

Docker出現後,容器技術在網際網路領域得到了空前的普及,無論是大公司還是屌絲創業公司的碼農基本上都會在各種技術社群或者各種演講會議上了解到過相關技術,我們作為一家屌絲創業公司也不例外,去年對Docker做了一番瞭解,並在年前測試了一些方案,今天在這裡總結一下遇到的各種坑以及踩坑過程中的一

GO程式設計基礎

1.常量的定義 --常量的值在編譯時就已經確定 --常量的定義格式與變數的基本相同 --等號右側必須是常量或者常量表達式 --常量表達式中函式必須是內建函式   const( PI = 3.14 SI = 1.15 CI = "test" ) co

YUV格式啟蒙及與RGB的轉換 -- 視訊和影象程式設計基礎

YUV和RGB詳解 前言 YUV,是一種顏色編碼方法。常使用在各個視訊處理元件中。 YUV在對照片或視訊編碼時,考慮到人類的感知能力,允許降低色度的頻寬。 YUV是編碼true-color時使用的顏色空間(color space)之一. 像Y'UV, YUV, Y

C++ 非同步程式設計探索) thread safe

前言 在非同步程式設計實踐中,曾經遇到的最大的問題就是thread safe 問題。 我所在的團隊是Database團隊,主要是為APP提供和redis互動的API。場景就是application thread呼叫我們的API。我們有個worker thread

【Java併發程式設計十:併發新特性—Lock鎖和條件變數(含程式碼)

簡單使用Lock鎖     Java 5中引入了新的鎖機制——java.util.concurrent.locks中的顯式的互斥鎖:Lock介面,它提供了比synchronized更加廣泛的鎖定操作。Lock介面有3個實現它的類:ReentrantLock、Reetrant

【Java併發程式設計:併發新特性—障礙器CyclicBarrier(含程式碼)

CyclicBarrier(又叫障礙器)同樣是Java 5中加入的新特性,使用時需要匯入java.util.concurrent.CylicBarrier。它適用於這樣一種情況:你希望建立一組任

Java併發程式設計系列十七:ThreadLocal

ThreadLocal簡介 ThreadLocal翻譯過來就是執行緒本地變數,初學者可能以為ThreadLocal是指一個Thread,其實說白了,ThreadLocal就是一個成員變數,只不過這是一個特殊的變數——變數值總是與當前執行緒(呼叫Thread.c

VS2013/MFC程式設計入門十六(常用控制元件:圖片控制元件Picture Control)

本節主要講一種簡單實用的控制元件,圖片控制元件Picture Control。通過使用圖片控制元件我們可以在介面某個位置顯示圖片以美化介面。        圖片控制元件簡介        圖片控制元件和前面講到的靜態文字框都是靜態文字控制元件,因此兩者的使用方法有很多

RPN 預備程式設計知識() : 函式篇章 bbox_transform.py

目錄 這個程式碼裡面主要是一些在anchor_targte_layer.py和proposals_layers.py中使用到的一些函式,比較簡單,主要是幫助以上兩個程式碼理解。 (2)   為什麼要做Bounding-box regressio

Java併發程式設計系列十六 ConcurrentModificationException

                        在多執行緒程式的

Java併發程式設計系列十 Fork/Join框架

                        Fork/Joi

【Java併發程式設計十三:併發新特性—訊號量Semaphore(含程式碼)

    在作業系統中,訊號量是個很重要的概念,它在控制程序間的協作方面有著非常重要的作用,通過對訊號量的不同操作,可以分別實現程序間的互斥與同步。當然它也可以用於多執行緒的控制,我們完全可以通過

VS2013/MFC程式設計入門十七(常用控制元件:列表檢視控制元件List Control 上)

      本節為大家詳解列表檢視控制元件List Control的使用。      列表檢視控制元件簡介        列表檢視控制元件List Control同樣比較常見,它能夠把任何字串內容以列表的方式顯示出來,這種顯示方式的特點是整潔、直觀,在實際應用中能為使

PHP中的traits(trait繼承中的優先順序)

       講到trait,在此我不得不提一下trait中的優先順序:        在trait繼承中,優先順序依次是:來自當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的

Java併發程式設計系列十一:CountdownLatch

CountDownLatch是JDK提供的併發工具包,理解並掌握這些工具包的使用有助於簡化特定場景下的程式設計。就CountDownLatch而言,允許一個或者多個執行緒等待其他執行緒完成操作。等待其他執行緒完成不是與Thread.join()方法類似嗎,因為T

VS2013/MFC程式設計入門十三(常用控制元件:列表框控制元件ListBox)

前面兩節講了比較常用的按鈕控制元件,並通過按鈕控制元件例項說明了具體用法。本文要講的是列表框控制元件(ListBox)及其使用例項。        列表框控制元件簡介        列表框給出了一個選項清單,允許使用者從中進行單項或多項選擇,被選中的項會高亮顯示。列表