# PHP-FPM过渡常驻内存
使用php开发的程序员大多数开发的都是web或者api接口,要么就是调用java的后端服务实现对外公开接口服务,这些开发大多数采用nginx+php-fpm模式来开发。
大多数的php开发者都没有常驻内存的概念,毕竟都是大多数都是基于fpm模式来进行开发,很多工作fpm都帮我们做好管理好了,php的开发者只需要管好自己的业务逻辑代码就已经足够了。
### 常驻内存和php-fpm模式有什么区别?
注意|常驻内存|php-fpm
-|-|-
变量|不释放|自动释放
对象|只new一次|每次请求都需要重新new
单例|在初始化阶段把对象存到内存|每个请求重建创建和销毁对象
### 在使用常驻内存框架需要注意什么?
* 内存释放
* 数据污染
* 资源释放
* 静态变量保存的对象不会被释放,需要手动管理
* 禁止使用exit和die
* 禁止使用sleep时间长的函数,防止导致Worker进程退出
* 不同Worker进程创建的对象和连接是不能互通的,创建连接池需要注意
* 定义公共函数的时候要使用 function_exists 判断函数是否存在,否则会提示重名
* 类引入文件需要使用 include_once 或者 require_once 否则会提示类名重复
* 修改代码需要重启服务才能生效
* echo、print_r、var_dump不会输出到浏览器
* 不能像fpm一样使用$_GET、$_POST、$_REQUEST、$_SESSION、$_COOKIE、$_SERVER等$_开头的变量。
### 数据污染问题演示
```php
<?php
Swoole\Runtime::enableCoroutine(true);
$_array = [];
$http = new swoole_http_server("127.0.0.1", 9501);
$http->set(['worker_num'=>1]);
$http->on("start", function ($server) {
});
$http->on("request", function ($request, $response) {
global $_array;
if ($request->server['request_uri'] == '/a') {
echo "---------------a请求开始----------------\n";
print_r($_array);
echo "---------------a请求开始----------------\n";
$_array['key'] = 'My Name is php';
co::sleep(1);
echo "---------------a请求修改----------------\n";
print_r($_array);
echo "---------------a请求修改----------------\n";
$response->end($_array['key']);
} else {
echo "---------------其他请求开始----------------\n";
print_r($_array);
echo "---------------其他请求开始----------------\n";
$_array['key'] = 'My name is Sunny';
echo "---------------其他请求修改----------------\n";
print_r($_array);
echo "---------------其他请求修改----------------\n";
$response->end();
}
});
$http->start();
```
- 第一章:基础知识
- 课程简介
- PHP-FPM过渡常驻内存
- 进程
- 实战:实现Master-Worker
- 线程
- 实战:CC攻击器
- 协程
- 实战:实现waitGroup功能
- 进程、线程、协程的区别
- 第二章:初识Swoft2.0
- Swoft介绍
- Swoft环境安装
- gcc升级
- 安装Swoft框架
- 目录结构介绍
- SwoftCli工具
- Swoft配置
- 第三章:Swoft2.0核心
- 上下文
- 常驻内存没有上下文隔离
- 实战:手写swoole框架上下文管理
- Bean容器
- 实战:根据容器原理实现容器
- 实战:通过容器实现依赖注入
- Bean容器定义与使用
- 配置文件定义Bean
- 容器类型
- 面向接口的容器
- 注解
- 实战:实现注解
- 自定义Swoft注解类
- 事件
- 连接池
- 实战:Swoole实现连接池
- 第四章:Http服务器
- Http Server生命周期
- Http Server配置
- 控制器
- 路由
- 请求对象Request
- 响应对象Response
- Http异常处理
- 中间件
- 实战:中间件实现JWT登陆授权
- 第五章:验证器
- 内置验证类型
- 验证器的使用
- 自定义验证器
- 第六章:数据库操作
- 连接数据库
- 实体模型
- 模型事件
- 查询器
- 事务处理
- 连接池配置
- 读写分离
- 多数据库切换
- Models分层结构
- 实战:实现用户CURD API
- 第七章:Redis
- 连接redis和使用
- Redis连接池
- Redis集群配置(单机版)
- Redis集群配置(多服务器)
- Redis连接集群
- Redis实战:实现延时任务
- 第八章:AOP编程
- AOP概念
- AOP实现原理
- 实战实现AOP:静态代理
- 实战实现AOP:动态代理
- 切面注解介绍
- PointExecution切面
- PointBean切面
- PointAnnotation切面
- 实战:使用AOP实现日志记录
- 第九章:任务处理
- 进程使用
- 进程池使用
- 实战:进程消费队列
- 实战:进程实现RabbitMQ延时队列
- 异步任务
- 协程任务
- 定时任务