第一次听说端口复用是在mixphp最新版本中发现的,mixphp启动监听9501端口,现在作者说可以多开几个进程来执行mixphp,我心里想了下再启动不是会端口冲突嘛,但是却没有问题,于是下载mixphp的源码解读,原来是启动http服务器使用new Co\Http\Server('0.0.0.0', 80, false, true); swoole这个http构造方法第4个参数是是否开启端口复用,这样就能多个进程来监听相同端口。底层负载调度由linux自动处理。切记需要linux3.10以上内核才支持。我们来做个试验。
【一】.基于swoole的端口复用
(1).创建t1.php:监听80端口
go(function () { $server = new Co\Http\Server('0.0.0.0', 80, false, true); $server->handle('/', function ($request, $response) { $response->end("<h1>T1 is work!</h1>"); echo 'replay from T1' . PHP_EOL; }); $server->start(); });
(2).创建t2.php:监听80端口
go(function () { $server = new Co\Http\Server('0.0.0.0', 80, false, true); $server->handle('/', function ($request, $response) { $response->end("<h1>T2 is work!</h1>"); echo 'replay from T2' . PHP_EOL; }); $server->start(); });
(3).通过ab.exe并发请求:
./ab.exe -n 1000 -c 1000 http://127.0.0.1/
(4).查看服务器php脚本输出:
replay from T2 replay from T1 replay from T2 replay from T1 replay from T1 replay from T2 replay from T1 replay from T2 replay from T1
(5).关闭t1脚本继续访问80端口:
replay from T2 replay from T2 replay from T2
通过上面的验证我们可以知道端口复用能够提高多核利用率,提高socket的处理能力,同时也实现了高可用,一个进程意外退出,其他继续工作,不需要重新建立socket句柄。另外端口重用解决了端口占用不能及时释放的问题,不释放我们可以直接重用。
【二】.基于原生socket的端口复用
(1).创建w1.php:监听8484端口
// 设置IP $host = '0.0.0.0'; // 设置端口 $port = 8484; // 创建socket $listen_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 设置端口复用 socket_set_option($listen_socket, SOL_SOCKET, SO_REUSEPORT, 1); // 绑定端口 socket_bind($listen_socket, $host, $port); // 监听socket socket_listen($listen_socket); // 事件轮询 while (true) { // 客户端 $client = socket_accept($listen_socket); // 向客户端发送消息 $msg = "This is w1\r\n"; // 记录响应来自哪个进程 echo 'replay from W1' . PHP_EOL; //发送消息 socket_write($client, $msg, strlen($msg)); //关闭客户端 socket_close($client); } socket_close($listen_socket);
(2).创建w2.php:监听8484端口
// 设置IP $host = '0.0.0.0'; // 设置端口 $port = 8484; // 创建socket $listen_socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 设置端口复用 socket_set_option($listen_socket, SOL_SOCKET, SO_REUSEPORT, 1); // 绑定端口 socket_bind($listen_socket, $host, $port); // 监听socket socket_listen($listen_socket); // 事件轮询 while (true) { // 客户端 $client = socket_accept($listen_socket); // 向客户端发送消息 $msg = "This is w2\r\n"; // 记录响应来自哪个进程 echo 'replay from W2' . PHP_EOL; //发送消息 socket_write($client, $msg, strlen($msg)); //关闭客户端 socket_close($client); } socket_close($listen_socket);
(3).并发后两个脚本的输出:
replay from W1 replay from W1 replay from W1 replay from W1 replay from W1 replay from W1 replay from W1 replay from W1 replay from W1 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2 replay from W2
Linux底层会自动负载均衡。
注意事项:
linux内核必须大于等于3.10以上
windows下的php原生socket不支持端口复用。
windows下的linux子系统wsl1暂时对内核实现不完整,测试不出负载调度效果。
先在centos安装openssl,然后开始://生成私钥openssl genrsa -out rsa_private_key.pem 1024//生成公钥openssl rsa -in rsa_private_key.pem&...
在PHP中,大部分变量类型,如字符串,整型,浮点,数组等都是值类型的,而类和对象是引用类型.和其他语言有点差距.(1).在值类型中我们直接使用&符号表示指向对应变量的内存地址,当前变量和被指向的变量只要有1个的值被修改都会直接影响另外一个变量的值发生变化。(ps:还是非常节省内存的,可以使用...
重构框架的时候想要考虑支持下cli模式,于是参考了thinkphp的底层。/** * 获取应用根目录 * @return string */ public static function getRootP...
elasticsearch的操作都是基于http协议的,已经有现成的php类库,composer安装即可。{ "require": { &...
(1).管道是干嘛的?管道是用于进程之间通信的,传播或交换信息(2).管道有几种?(2.1).匿名管道(pipe):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。通常是指父子进程关系。(2.2).高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中...
本文基于Laravel Framework 6.17.1版本(1).创建项目(依赖真多,如此臃肿)composer create-project --prefer-dist laravel/laravel blog(2).安装定时任务composer包&nbs...