background image

if

 (curl_multi_select(

$queue

, 0.5) != -1) { 

do

 { 

$mrc

 = curl_multi_exec(

$queue

$active

); 

while

 (

$mrc

 == CURLM_CALL_MULTI_PERFORM); 



 

$responses

 = 

array

(); 

foreach

 (

$map

 

as

 

$url

=>

$ch

) { 

$responses

[

$url

] = callback(curl_multi_getcontent(

$ch

), 

$delay

); 

curl_multi_remove_handle(

$queue

$ch

); 

curl_close(

$ch

); 


 
curl_multi_close(

$queue

); 

return

 

$responses


 
首先将所有的

URL 压入并发队列, 然后执行并发过程, 等待所有请求接收完之后进行数据的

解析等后续处理

. 在实际的处理过程中, 受网络传输的影响, 部分 URL 的内容会优先于其他

URL 返回, 但是经典 cURL 并发必须等待最慢的那个 URL 返回之后才开始处理, 等待也就意
味着

CPU 的空闲和浪费. 如果 URL 队列很短, 这种空闲和浪费还处在可接受的范围, 但如果

队列很长

, 这种等待和浪费将变得不可接受. 

 
2. 改进的 Rolling cURL 并发方式 
 
仔细分析不难发现经典

cURL 并发还存在优化的空间, 优化的方式时当某个 URL 请求完毕

之后尽可能快的去处理它

, 边处理边等待其他的 URL 返回, 而不是等待那个最慢的接口返回

之后才开始处理等工作

, 从而避免 CPU 的空闲和浪费. 闲话不多说, 下面贴上具体的实现: 

代码如下

function

 rolling_curl(

$urls

$delay

) { 

$queue

 = curl_multi_init(); 

$map

 = 

array

(); 

 

foreach

 (

$urls

 

as

 

$url

) { 

$ch

 = curl_init(); 

 
curl_setopt(

$ch

, CURLOPT_URL, 

$url

); 

curl_setopt(

$ch

, CURLOPT_TIMEOUT, 1); 

curl_setopt(

$ch

, CURLOPT_RETURNTRANSFER, 1); 

curl_setopt(

$ch

, CURLOPT_HEADER, 0); 

curl_setopt(

$ch

, CURLOPT_NOSIGNAL, true); 

 
curl_multi_add_handle(

$queue

$ch

);