在《nginx-3》《nignx-4》的基础上,建立一个多进程、异步、io复用的服务器。
class Server{
private $pids;
private $_mainSocket; //server
private $_newSocket; //client
private $_EventBase; //eventbase
public function __construct()
{
$this->forkServer();
}
//创建三个子进程
public function forkServer($count=3)
{
for ($i = 0; $i < $count; ++$i)
{
$pid = pcntl_fork();
if ($pid < 0) {
exit('生成子进程失败\n');
} else if ($pid > 0) {
// 父进程
$this->pids[] = $pid;
} else {
$this->listen();
exit;
}
}
pcntl_wait($status); //阻塞
}
public function listen ()
{
$tcp = "0.0.0.0:6001";
$context = stream_context_create([
'socket' => [
'backlog' => 102400
]
]);
//设置地址重用
stream_context_set_option($context,'socket','so_reuseaddr',1);
//开启监听端口复用 让三个子进程可以同时监听6001端口
//允许多个无亲缘关系的进程监听相同的端口,并且由系统内核做负载均衡,决定将socket连接交给哪个进程处理
stream_context_set_option($context , 'socket' , 'so_reuseport' , 1);
$this->_mainSocket = stream_socket_server($tcp , $errno , $errstr , STREAM_SERVER_BIND | STREAM_SERVER_LISTEN , $context);
stream_set_blocking($this->_mainSocket , false); //异步非阻塞
$this->_EventBase = new \EventBase();
$event=new \Event( $this->_EventBase,$this->_mainSocket,Event::READ | Event::PERSIST,function (){
$this->_newSocket = stream_socket_accept($this->_mainSocket);
stream_set_blocking($this->_newSocket , false);//异步非阻塞
//触发客户端事件
$event=new \Event( $this->_EventBase , $this->_newSocket , Event::READ | Event::PERSIST ,function($socket)use(&$event){
$msg = fread($socket , 65535);
if ($msg === '') {
if ((feof($socket) || !is_resource($socket))) {
$event->del();
return null;
}
}else{
$content = '<p>我是需要访问的内容</p>';
$header = "HTTP/1.1 200 OK\r\n";
$header .= "Content-Type: text/html;charset=utf-8\r\n";
$header .= "Connection: keep-alive\r\n";
$header .= "Content-Length: " . strlen($content) . "\r\n\r\n";
fwrite($socket,$header . $content);
}
},$this->_newSocket);
$event->add();
});
$event->add();
$this->_EventBase->loop();
}
}
$server=new Server();
启动
安装压测工具
yum install httpd-tools
简单的压测
结果
从阻塞的http服务器到多进程http服务器,从短连接到keep-alive,现在已能轻松处理10W的数据了(_)