1.PHP的生命周期
PHP有多进程版本和多线程(TSRM)版本,它们的生命周期如下:


整个PHP的生命周期如下:

流程为:
1.模块初始化(1.GINIT()全局资源初始化2.MINIT()模块初始化)
2.请求处理(1.请求初始化2.处理请求3.释放请求资源)
3.释放模块资源,释放全局资源
2.如何做到常驻内存?
很简单,只要让脚本不退出,资源自然不会释放。而swoole和workman使用了内置的webserver,它们都是阻塞监听正常情况下永远不会退出的 php-cli脚本,所以每次客户端请求过来的时候,可以直接使用常驻内存中的框架代码处理请求,而不用像PHP-FPM一样,每次都要重新初始化资源,执行脚本完以后再释放资源。
3.常驻内存做法的弊端
对于每次请求,不会重新初始化和释放资源,导致很多资源处于常驻状态。每次请求这些资源实际上访问的都是上一次请求所处理的结果。如果你的类里有成员变量,你对成员变量的操作++–的结果都会保留到下一次请求中,另外session的生命周期也被破坏,每次请求过来,获取的session都是上一次请求的session,所以我们需要自己维护session的周期(每次请求需要设置session_id),或者不用session,放redis里也可以,通过onclose回调可以主动释放部分资源。
4.代码演示
<?php
class WebServer
{
public $onRequest;
public function __construct()
{
}
public function run()
{
$socket = stream_socket_server(
'tcp://0.0.0.0:7777',
$errno,
$errstr
);
if (!$socket) {
echo "$errstr ($errno)" . PHP_EOL;
} else {
while ($conn = stream_socket_accept($socket)) {
$response = '';
if ($this->onRequest) {
$response = call_user_func($this->onRequest, $conn);
}
$responseheader = $httpResponse = "HTTP/1.1 200 OK\r\n";
$responseheader .= "Content-Type:text/html;charset=utf-8\r\n";
$responseheader .= "Content-Length: ".strlen((string)$response). "\r\n\r\n";
fwrite($conn, $responseheader.$response);
fclose($conn);
}
}
}
}
class A
{
private $a;
public static $static_a;
public function __construct()
{
session_start();
$_SESSION['a'] = 1;
}
public function plusA()
{
$this->a++;
static::$static_a++;
}
public function getA()
{
$res = 'none-static:' . $this->a . PHP_EOL;
$res .= 'static:' . static::$static_a . PHP_EOL;
return $res;
}
}
$a = new A();
$server = new WebServer();
$server->onRequest = function($conn) use($a) {
$a->plusA();
return $a->getA() . 'session:' .$_SESSION['a'] . PHP_EOL;
};
$server->run();
这里不考虑高性能,直接演示一个最基础的套接字模型。

