专栏首页魔王卷子的专栏parallel-request-testing

parallel-request-testing

并行请求测试

因为我们想要做底层服务,那么肯定会有一个对外的接口中会有好几个调用底层的接口。按照传统做法,就只能是串行请求。下面我做了一个测试。测试使用各种方法连续请求10次,看看总的统计时间,来确定使用哪种方案。

使用版本:

  • PHP: 7.3.8
  • PHP-Swoole: 4.4.8
  • PHP-cURL: 7.65.3
  • Node.js:
  • GoLang:

串行读取

首先呢,就是PHP的默认串行读取了。接下来直接看脚本吧:

$urls = [
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
];

foreach($urls as $item) {
    geturl($item);
}
	
function geturl($url){
       
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS      => 5,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_URL => "http://" . $url,
        ]);
        
        $output = curl_exec($ch);
        curl_close($ch);
 
        var_dump(strlen($output));
}

执行时间:

real    0m1.150s
user    0m0.045s
sys     0m0.040s

CURL并发请求

$urls = [
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
];

$rolling_window = count($urls);
 
$master   = curl_multi_init();
$curl_arr = array();
 
$std_options = array(
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_MAXREDIRS      => 5,
    CURLOPT_RETURNTRANSFER => true,
);

$options = $std_options;
 
for ($i = 0; $i < $rolling_window; $i++) {
    $ch                   = curl_init();
    $options[CURLOPT_URL] = "http://" . $urls[$i];
    curl_setopt_array($ch, $options);
    curl_multi_add_handle($master, $ch);
}

$result = [];

do {
    while (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM);
    if ($execrun != CURLM_OK) {
        break;
    }

    while ($done = curl_multi_info_read($master)) {
        $info = curl_getinfo($done['handle']);
        $output = curl_multi_getcontent($done['handle']);
        var_dump(strlen($output));
        curl_multi_remove_handle($master, $done['handle']);
    }
} while ($running);
 
curl_multi_close($master);

执行时间:

real    0m0.246s
user    0m0.081s
sys     0m0.173s

Swoole 协程请求

Swoole\Runtime::enableCoroutine();

$urls = [
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
    "cn.bing.com",
];

$chan = new chan(count($urls));

go(function() use($chan, $urls) {
    foreach($urls as $item) {
        var_dump($chan->pop());
    }
});

foreach($urls as $url) {
    go(function() use($chan, $url) {
        $cli = new Swoole\Coroutine\Http\Client('cn.bing.com', 80);
        $ret = $cli->get('/');

        $chan->push([$url => strlen($cli->getBody())]);
    });
}

执行时间:

real    0m0.140s
user    0m0.019s
sys     0m0.031s

Golang协程

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	ch := make(chan string)

	urls := []string{
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
		"https://www.baidu.com",
	};

	for _, url := range urls {
		go fetch(url, ch) // start a goroutine
	}
	for range urls {
		<-ch
	}
}

func fetch(url string, ch chan<- string) {
	resp, err := http.Get(url)
	if err != nil {
		ch <- fmt.Sprint(err) // send to channel ch
		return
	}

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp.Body.Close()
	ch <- string(len(body))
}

执行时间:0.185s

NodeJS

const axiso = require('axios');
const urls = [
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
    "https://www.baidu.com",
];

async function fetchAll() {
  const promiseAll=[];
  urls.forEach(url => {
      promiseAll.push(fetch(url));
  });
  const res = await Promise.all(promiseAll);
  res.forEach(val=>{
    //   console.log(val.data.length);
  })
}

async function fetch(url) {
  return axiso.get(url)
}

fetchAll();

运行时间 0.344s

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 我的电脑系统换成了linux之WEB 环境搭建

    这个时候默认安装是php7.1的,不得不说,ubuntu对于php的更新还是比较频繁的,因为我之前用的centos7.4使用的php版本好像还是5.4的,无语了...

    魔王卷子
  • SPL标准库之SplDoublyLinkedList(双向链表)

    双向链表其实就是数据本身具备了左边和右边的双向指针。类似Redis的列表,它就是双向链表。

    魔王卷子
  • sentry配置邮件

    sentry一个最大的好处就是可以使用邮件通知功能,如果没有邮件通知,那么我们自己上去看的话就非常麻烦了。

    魔王卷子
  • 2位数字域名竟千万 交易动态一起看

    2数字域名80.com完成交易了,价格高达千万元人民币!让我们一起看下本周域名交易动态吧!

    躲在树上的域小名
  • 三个含义不错的双拼域名相继结拍

    域名圈内常有好消息爆出,品相兼优的域名交易的消息更是不曾停过,最近chanchan.com、shoumai.com等3个域名都相继结拍了。

    躲在树上的域小名
  • 130 个相见恨晚的神器网站

    猴哥yuri
  • 浅谈Solr和ElasticSearch建索引性能优化策略

    我是攻城师
  • 什么是 RESTful Web服务

    总结就是: 上面的提到的特点,可以总结为“ 用明确的方法 操作 语义清晰的资源,来呈现不同的资源表现形式”。

    zhangyunfeiVir
  • Java开发必知道的国外10大网站

    1、https://www.google.com/ ? 不解释 2、https://stackoverflow.com ? 里面包含各种开发遇到的问题及答案,质...

    Java技术栈
  • “瑞波币”全套三拼域名被同买家收入囊中

    最近一段时刻,有关区块链的论题开端进入群众的视界。区块链技能被认为是继蒸汽机、电力、互联网之后,下一代颠覆性的中心技能。未来对买房卖房的房产职业也会...

    躲在树上的域小名

扫码关注云+社区

领取腾讯云代金券