壓測 swoole_websocket_server 效能
概述
這是關於 Swoole 入門學習的第十篇文章:壓測 swoole_websocket_server 效能。
- 第九篇:Swoole Redis 連線池的實現
- 第八篇:Swoole MySQL 連線池的實現
- 第七篇:Swoole RPC 的實現
- 第六篇:Swoole 整合成一個小框架
- 第五篇:Swoole 多協議 多埠 的應用
- 第四篇:Swoole HTTP 的應用
- 第三篇:Swoole WebSocket 的應用
- 第二篇:Swoole Task 的應用
- 第一篇:Swoole Timer 的應用
收到讀者提問 “使用 Swoole 開發的群聊功能,想知道併發情況,也就是想壓測下 QPS,一直未找到方法 ...”
對 swoole_http_server 壓測,咱們可以使用 Apache 的 ab 命令。
對 swoole_websocket_server 壓測,使用 ab 命令是不能壓測的,我從網上一直也沒找到合適的方法,看官方提供的程式碼 benchmark/async.php
中,使用的非同步模組 swoole\http\client
方法進行壓測的,但在 Swoole 4.3 版本就移除了非同步模組,讓使用 Coroutine
協程模組。
在本地我用 Coroutine
協程實現了一下, 測的差不多的時候,一直不確定是否正確,就在 segmentfault 發了個提問,沒想到韓老師回答了,'如果的如果'老師也回答了,非常感謝兩位老師的答案,然後整理出文章分享給大家。
測試機
Mac 上安裝的 Parallels Desktop 虛擬機器
系統:Ubuntu 16.04.3 LTS
記憶體:
- 數量:1
- 核數:2
CPU:
- 數量:1
- 大小:2G
Server 程式碼
<?php class Server { private $serv; public function __construct() { $this->serv = new Swoole\WebSocket\Server("0.0.0.0", 9501); $this->serv->set([ 'task_worker_num' => 10, 'enable_coroutine' => true, 'task_enable_coroutine' => true ]); $this->serv->on('open', function ($serv, $request) {}); $this->serv->on('message', function ($serv, $frame) { $serv->task($frame->data); }); $this->serv->on('task', function ($serv, $task) { foreach ($serv->connections as $fd) { $connectionInfo = $serv->connection_info($fd); if (isset($connectionInfo['websocket_status']) && intval($connectionInfo['websocket_status']) == 3) { $serv->push($fd, $task->data); } } }); $this->serv->on('finish', function ($serv, $task_id, $data) {}); $this->serv->on('close', function ($serv, $fd) {}); $this->serv->start(); } } $server = new Server();
壓測指令碼
class Test
{
protected $concurrency; //併發量
protected $request; //請求量
protected $requested = 0;
protected $start_time;
function __construct()
{
$this->concurrency = 100;
$this->request = 10000;
}
protected function webSocket()
{
go(function () {
for ($c = 1; $c <= $this->concurrency; $c++ ) {
$cli = new \Swoole\Coroutine\Http\Client('127.0.0.1', 9501);
$cli->set(['websocket_mask' => false]);
$ret = $cli->upgrade('/');
if ($ret) {
$i = $this->request / $this->concurrency;
while ($i >= 1) {
$this->push($cli);
$cli->recv();
$i--;
}
}
}
$this->finish();
});
}
protected function push($cli)
{
$ret = $cli->push('Hello World');
if ($ret === true) {
$this->requested ++ ;
}
}
protected function finish()
{
$cost_time = round(microtime(true) - $this->start_time, 4);
echo "Concurrency:".$this->concurrency.PHP_EOL;
echo "Request num:".$this->request.PHP_EOL;
echo "Success num:".$this->requested.PHP_EOL;
echo "Total time:".$cost_time.PHP_EOL;
echo "Request per second:" . intval($this->request / $cost_time).PHP_EOL;
}
public function run()
{
$this->start_time = microtime(true);
$this->webSocket();
}
}
$test = new Test();
$test->run();
壓測結果
第 1 次:
Concurrency:100
Request num:10000
Success num:10000
Total time:0.846
Request per second:11820
第 2 次:
Concurrency:100
Request num:10000
Success num:10000
Total time:0.9097
Request per second:10992
第 3 次:
Concurrency:100
Request num:10000
Success num:10000
Total time:0.903
Request per second:11074
以上是壓測結果,供參考。
小結
通過這個壓測結果,表明 Swoole 的執行效率是槓槓的!
當然還有一些引數是可以調優的,比如:worker_num、max_request、task_worker_num 等。
在真實的業務場景中,肯定會有邏輯處理,也會使用到 MySQL、Redis。
那麼問題來了,前兩篇文章已經分享了,Swoole Redis 連線池、Swoole MySQL 連線池,感興趣的同學,可以使用上兩種連線池,然後再進行壓測。
不知不覺,Swoole 入門文章已經寫了 10 篇了,非常感謝大家的捧場,真心希望能夠對 Swoole 入門學習的同學,有點幫助。
本文歡迎轉發,轉發請註明作者和出處,謝謝