语言

版本

PHP5

  • PHP5.0 : 使用了Zend 2 引擎,增加了新关键字,包括this,try,catch,public,private,protected等
  • PHP5.1:PDO扩展默认启动、性能优化、修复了超过400个bug
  • PHP5.2:新增Zip、Filter 、JSON 扩展
  • PHP5.3:弃用的功能,匿名函数(又叫闭包函数,1,2),新增魔术方法,命名空间,后期静态绑定,Heredoc 和 Nowdoc, const, 三元运算符,Phar
  • PHP5.4:闭包 支持 $this,Short Open Tag, 数组简写形式,Traits, 内置用于开发的 CLI 模式的 web server ,SESSION 扩展能追踪文件的上传进度
  • PHP5.5:yield(生成器用法、协程),list() 用于 foreach,finally关键字,opcache扩展
  • PHP5.6:支持大于 2GB 的文件上传,常量增强,可变函数参数,命名空间增强,pgsql 扩展现在支持 异步方式连接数据库及执行查询

PHP6

旨在为 PHP提供完全内置的unicode的支持,由于困难,最终取消。

PHP7

  • PHP7.0 使用了Zend Engine 3.0性能升级,匿名类,标量类型声明,返回值类型声明,太空船操作符, 单个 use 语句 一次性可以导入多个类、函数和常量 生成器可以返回表达式 JSON 扩展已经被 JSOND 取代 listen 端口现在同时监听 IPv4 和 IPv6 地址 更多参考资料 PHP7新特性总结 从 PHP 5.6.x 移植到 PHP 7.0.x
  • PHP7.1 可为空(Nullable)类型 、新增 void 类型、类常量可见性、iterable 伪类 多异常捕获处理 list支持键名 字符串支持负向 curl支持推送http2
  • PHP7.2 新的对象类型object 、允许重写抽象方法(Abstract method)、允许分组命名空间的尾部逗号
  • PHP7.3 更灵活的Heredoc和Nowdoc、 数组析构支持引用赋值 list结构支持引用解析。 instanceof 运算符支持字面量语法 LDAP 全支持 性能提升 废弃大小写不敏感的常量
  • PHP7.4 预加载 、FFI、类属性的类型支持

PHP8

  • PHP8.0 JIT 注解的功能 构造器属性提升功能(在构造函数中声明类的属性) 联合类型 Match 表达式 Nullsafe 运算符(?->)

PHP7比PHP5性能高原因(2倍提升)

  1. 变量存储字节减小,减少内存占用,提升变量操作速度
  2. 改善数组结构,数组元素和hash映射表被分配在同一块内存里,降低了内存占用,提升cpu缓存命中率
  3. 改进了函数调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率

类与对象

PHP标准库(SPL)

数据结构

迭代器

接口

异常

SPL函数

文件处理

各种类及接口

框架

Laravel

生命周期

第一步

入口点 public/index.php,加载 composer 生成的自动加载器定义,然后从 bootstrap/app.php 中检索 Laravel 应用程序实例。

HTTP / Console 内核

接下来,根据进入应用的请求类型,传入的请求将被发送到 HTTP 内核或者 Console 内核。

引导程序用来配置异常处理、配置日志、检测应用程序环境,并执行在实际处理请求之前需要完成的其他任务。

HTTP 内核还定义了一个 HTTP 中间件 列表,所有请求在被应用程序处理之前都必须通过该列表。

HTTP 内核的 handle 方法的签名非常简单:它接收 Request 接口并返回 Response 接口。

服务提供者

最重要的内核引导操作之一是为应用程序加载 服务提供者 。应用程序的所有服务提供程序都在 config/app.php 文件中的 providers 数组。

服务提供者是所有Laravel应用程序的引导中心,或理解为注册,比如注册服务容器绑定,事件监听器,中间件,甚至路由。是配置应用程序的中心。

Facades 充当服务容器中底层类的静态代理,提供简洁、富有表现力的好处,同时保持比传统静态方法更多的可测试性核灵活性。是一个提供从容器访问对象的类

路由

应用程序中最重要的服务提供者之一是 App\Providers\RouteServiceProvider。此服务提供者加载应用程序的 routes 目录中包含的路由文件。

一旦应用程序被引导并且所有服务提供者都被注册,「请求」将被传递给路由器进行调度。路由器将请求发送到路由或控制器,并运行任何路由特定的中间件。

如果请求通过了所有匹配路由分配的中间件,则执行路由或控制器方法,并通过路由的中间件链路返回路由或控制器方法的响应。

最后

一旦路由或控制器方法返回一个响应,该响应将通过路由的中间件返回,从而使应用程序有机会修改或检查传出的响应

依赖注入(dependency injection)

  • 谁依赖谁
  • 注入什么,自动注入主要依赖反射功能,是控制反转的一种实现方式。

控制反转(Inversion Of Control, IOC)

面向对象编程中一种设计原则,减少代码之间的耦合(只依赖接口,不依赖具体实现),将控制权交给容器,在运行时容器将具体的实现动态的“注入”到调用类的对象中。

  • 谁控制谁
  • 反转什么

容器是什么

你把需要的类丢给容器处理,容器去反射寻找这个类的参数

Hyperf

框架生命周期

swoole生命周期

swoole_server中对象的4层生命周期

变量、对象、资源、require/include的文件等下面统称为对象

程序全局期

swoole_server->start之前就创建好的对象,我们称之为程序全局生命周期。这些变量在程序启动后就会一直存在,直到整个程序结束运行才会销毁。

有一些服务器程序可能会连续运行数月甚至数年才会关闭/重启,那么程序全局期的对象在这段时间持续驻留在内存中的。程序全局对象所占用的内存是 Worker进程间共享的,不会额外占用内存。

这部分内存会在写时分离(COW),在 Worker进程内对这些对象进行写操作时,会自动从共享内存中分离,变为进程全局对象。

程序全局期 include/require的代码,必须在整个程序 shutdown时才会释放,reload无效

进程全局期

swoole拥有进程生命周期控制的机制,一个 Worker子进程处理的请求数超过max_request配置后,就会自动销毁。Worker进程启动后创建的对象(onWorkerStart中创建的对象),在这个子进程存活周期之内,是常驻内存的。onConnect/onReceive/onClose 中都可以去访问它。

进程全局对象所占用的内存是在当前子进程内存堆的,并非共享内存。对此对象的修改仅在当前 Worker进程中有效 进程期include/require的文件,在 reload后就会重新加载

会话期

onConnectonClose是一次TCP的会话周期,http keep-alive时,一个连接可能会有多个request。 http是无状态的,一个用户可能也不止一个连接,可以通过创建一个session来关联同一个用户的不同请求。

请求期

请求期就是指一个完整的请求发来,也就是 onReceive收到请求开始处理,直到返回结果发送 response。这个周期所创建的对象,会在请求完成后销毁。

swoole中请求期对象与普通PHP程序中的对象就是一样的。请求到来时创建,请求结束后销毁。

请求与协程生命周期

Swoole 在处理每个连接时,会默认创建一个协程去处理,主要体现在 onRequestonReceiveonConnect 事件,所以可以理解为每个请求都是一个协程,由于创建协程也是个常规操作,所以一个请求协程里面可能会包含很多个协程,同一个进程内协程之间是内存共享的,但调度顺序是非顺序的,且协程间本质上是相互独立的没有父子关系,所以对每个协程的状态处理都需要通过 协程上下文 来管理。

短生命周期对象

new 关键字创建的对象,可以使用make创建一个短生命周期对象又可以使用依赖注入功能。

容器仅管理长生命周期对象

换种方式理解就是容器内管理的对象 都是单例 ,这样的设计对于长生命周期的应用来说会更加的高效,减少了大量无意义的对象创建和销毁,这样的设计也就意味着所有需要交由 DI 容器管理的对象均不能包含 状态 值。 状态 可直接理解为会随着请求而变化的值,事实上在 协程 编程中,这些状态值也是应该存放于 协程上下文 中的,即 Hyperf\Context\Context

Yii2

待补充……

PHP-FPM配置与优化

进程管理模式使用

  • 内存大 (4G以上)并对并发和可用性要求的话,建议使用 static + pm.max_children(最大进程数)
  • 小内存 (1G以上)建议使用 dynamic 或 (0.5G上下)建议使用 ondemand 模式,降低 pm.start_servers(启动时进程数)pm.max_spare_servers (最大空闲数)进程数

backlog 大小问题

一个php-fpm子进程在同一时间只能处理一个进程,nginx发起的请求没有fpm进程进行accept,nginx就会断掉改连接,等fpm忙起来再去accept时,就会发现已断开,报错503

backlog设置过小,fpm紫禁城全部处于忙碌状态,backlog也塞满了,就会拒绝新的连接,nginx再去请求就会被拒。

backlog 一般设置2的幂,可参考内核 somaxconn

php-fpm进程数,每个php-fpm占用内存、平均内存占用

pm.max_requests 最大请求数 达到后释放,避免内存泄漏

request_terminate_timeout 最长执行时间优化