easyswoole框架生命周期
具体可参考核心代码文件:vendor/easyswoole/easyswoole/src/Core.php
框架生命周期
服务类型
EASYSWOOLE_SERVER (对应Swoole\Server)
EASYSWOOLE_WEB_SERVER (对应Swoole\Http\Server)
EASYSWOOLE_WEB_SOCKET_SERVER (对应Swoole\WebSocket\Server)
easyswoole案例演示
tcp请求:
#在CliExample目录下执行 php TCPClient3.php
服务端回复: 1557998515
服务端回复: your args is:{"name":"\u4ed9\u58eb\u53ef"}
#服务端内容响应:
已连接
tcp服务3 fd:3 发送消息:M{"controller":"Index","action":"index","param":{"name":"\u4ed9\u58eb\u53ef"}}
tcp服务3 fd:3 发送消息:L{"controller":"Index","action":"args","param":{"name":"\u4ed9\u58eb\u53ef"}}
tcp服务3 fd:3 已关闭
服务端通过addListener开启9504端口监听,客户端通过$client->connect('127.0.0.1', 9504, 0.5)发起链接后发送数据。服务端通过\EasySwoole\Socket\Dispatcher->dispatch进行路由解析,并执行具体动作后将数据返回给客户端。
http请求:
#按照demo案例添加App/HttpController/Test.php,并访问以下函数
function index()
{
$this->response()->write('test index');
}
# 访问 http://mytest.easyswoole.com/Test/index
输出:test index
压力测试:
#硬件信息
CPU:1核 Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
内存:1GB
操作系统: Ubuntu / 16.04 LTS amd64 (64bit)
# ab长连接压测swoole页面(ab -c 100 -n 100000 -k http://127.0.0.1:9501/Test/index)返回:
Concurrency Level: 100
Time taken for tests: 18.085 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 15500000 bytes
HTML transferred: 1000000 bytes
Requests per second: 5529.44 [#/sec] (mean)
Time per request: 18.085 [ms] (mean)
Time per request: 0.181 [ms] (mean, across all concurrent requests)
Transfer rate: 836.98 [Kbytes/sec] receive
#ab非长连接压测swoole页面(ab -c 100 -n 100000 http://127.0.0.1:9501/Test/index)返回:
Concurrency Level: 100
Time taken for tests: 46.141 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 15000000 bytes
HTML transferred: 1000000 bytes
Requests per second: 2167.29 [#/sec] (mean)
Time per request: 46.141 [ms] (mean)
Time per request: 0.461 [ms] (mean, across all concurrent requests)
Transfer rate: 317.47 [Kbytes/sec] received
#ab长连接压测nginx页面(ab -c 100 -n 100000 -k http://127.0.0.1/test.php)返回:
Concurrency Level: 100
Time taken for tests: 36.257 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 0
Total transferred: 14700000 bytes
HTML transferred: 1000000 bytes
Requests per second: 2758.12 [#/sec] (mean)
Time per request: 36.257 [ms] (mean)
Time per request: 0.363 [ms] (mean, across all concurrent requests)
Transfer rate: 395.94 [Kbytes/sec] received
swoole页面的长连接比非长连接qps高出一半,nginx非长连接压测的qps比swoole非长连接压测的qps要高
自定义进程
#按照demo部署代码,并稍微调整EasySwooleEvent.php下函数mainServerCreate代码
public static function mainServerCreate(EventRegister $register)
{
/**
* 除了进程名,其余参数非必须
*/
for($i=0;$i<3;$i++){
$myProcess = new ProcessOne("processName".$i,$i,false,2,true);
ServerManager::getInstance()->getSwooleServer()->addProcess($myProcess->getProcess());
}
}
#稍微调整App/Process/ProcessOne.php代码
public function run($arg)
{
Logger::getInstance()->console($this->getProcessName().'-'.$arg." start");
while (1){
\co::sleep(4-$arg);
Logger::getInstance()->console($this->getProcessName().'-'.$arg." run");
}
}
#查询执行的进程:
root@instance-wjbdyzhe:/data/web/mytest.easyswoole.com# ps -aux|grep processName
root 10288 0.0 0.0 14688 908 pts/0 S+ 20:53 0:00 grep --color=auto processName
root 24261 0.0 1.2 232932 12308 pts/2 S+ 20:04 0:00 processName0
root 24262 0.0 1.2 232932 12308 pts/2 S+ 20:04 0:00 processName1
root 24263 0.0 1.2 232932 12308 pts/2 S+ 20:04 0:00 processName2
#三个进程的执行结果:
[2019-04-28 08:56:37][default]processName0-0 start
[2019-04-28 08:56:37][default]processName2-2 start
[2019-04-28 08:56:37][default]processName1-1 start
[2019-04-28 08:56:39][default]processName2-2 run
[2019-04-28 08:56:40][default]processName1-1 run
[2019-04-28 08:56:41][default]processName0-0 run
[2019-04-28 08:56:41][default]processName2-2 run
[2019-04-28 08:56:43][default]processName1-1 run
[2019-04-28 08:56:43][default]processName2-2 run
可以看到以上代码及执行结果:执行程序后,创建了三个自定义进程,并且进程是并行执行的
异步任务:
#按照demo部署代码,并调整以下函数
function multiTaskConcurrency(){
// 多任务并发
$tasks[] = function () { sleep(1);return 'this is 1'; }; // 任务1
$tasks[] = function () { sleep(5);return 'this is 2'; }; // 任务2
$tasks[] = function () { sleep(3);return 'this is 3'; }; // 任务3
$results = \EasySwoole\EasySwoole\Swoole\Task\TaskManager::barrier($tasks, 6);
var_dump($results);
$this->response()->write('执行并发任务成功');
}
# 访问 http://mytest.easyswoole.com/index/multiTaskConcurrency
输出:
array(3) {
[0]=>
string(9) "this is 1"
[2]=>
string(9) "this is 3"
[1]=>
string(9) "this is 2"
}
由代码和打印来看,虽然任务2排在第二位,但由于执行时间长,执行结果排在最后,由此可知三个任务并非串行执行,而是并行执行
连接池
#最大进程配置数8个
'SETTING' => [
'worker_num' => 8,
'max_request' => 5000,
'task_worker_num' => 8,
'task_max_request' => 1000,
],
#每个进程连接池最大连接个数5个
'REDIS' => [
'host' => '127.0.0.1',
'port' => '6379',
'auth' => 'test',
'POOL_MAX_NUM' => '5',
'POOL_TIME_OUT' => 'utf8mb4',
],
#jmeter压测配置
线程数:100;ramp-up时间:10;循环次数:30
#通过redis客户端查看链接信息:
127.0.0.1:6379> info clients
# Clients
connected_clients:41
client_recent_max_input_buffer:4
client_recent_max_output_buffer:0
blocked_clients:0
理论最大redis链接数 = worker_num*POOL_MAX_NUM = 8*5 = 40
并发压测客户端显示 = 41-1 = 40(多一个1实际为手动链接)
只要不终止swoole/server服务客户端连接,显示一直为41,表示链接一直处于链接可用状态。
#最大进程配置数8个
'SETTING' => [
'worker_num' => 8,
'max_request' => 5000,
'task_worker_num' => 8,
'task_max_request' => 1000,
],
#匿名连接池最大配置10个链接
'MYSQL3' => [
'host' => '127.0.0.1',//防止报错,就不切换数据库了
'port' => '3306',
'user' => 'root',
'timeout' => '5',
'charset' => 'utf8mb4',
'password' => '123456',
'database' => 'test',//防止报错,就不切换数据库了
'POOL_MAX_NUM' => '10',
'POOL_TIME_OUT' => '0.1'
],
#jmeter压测配置
线程数:100;ramp-up时间:10;循环次数:30
#通过mysql查看链接个数
mysql> show processlist;
……
| 306155 | root | 172.17.0.1:48704 | test | Sleep | 30 | | NULL |
| 306156 | root | 172.17.0.1:48840 | test | Sleep | 36 | | NULL |
| 306157 | root | 172.17.0.1:48846 | test | Sleep | 29 | | NULL |
+--------+------+------------------+------+---------+------+----------+------------------+
81 rows in set (0.00 sec)
理论最大mysql链接数 = worker_num*POOL_MAX_NUM = 8*10 = 80
并发压测客户端显示 = 81-1 = 80(多一个1实际为手动链接)
过一段再show processlist发现已无链接,可能mysql主动超时中断,有兴趣的同学可主动排查