PHP 知识

nginx 如何配置负载均衡:#

在 nginx 里面配置一个 upstream,然后把相关的服务器 ip 都配置进去。然后采用轮询的方案,然后在 nginx 里面的配置项里,proxy-pass 指向这个 upstream,这样就能实现负载均衡。

什么是 CGI?#

CGI 是一种通用网关协议。为了解决不同的语言解释器 (如 php 、 python 解释器) 与 WebServer 的通信而产生的一种协议。只要遵守这种协议就能实现语言与 WebServer 通讯。CGI 是规定了要传什么数据/以什么格式传输给 php 解析器的协议。

什么是 FastCGI?#

是一种对 CGI 协议升华的一种协议。FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次 (这是 CGI 最为人诟病的 fork-and-execute 模式)。它还支持分布式的运算,即 FastCGI 程序可以在网站服务器以外的主机上执行并且接受来自其它网站 服务器 来的请求。。

什么是 PHP-FPM?#

(PHP FastCGI Process Manager),PHP-FPM 是一个实现了 Fastcgi 协议的程序,用来管理 Fastcgi 起的进程的,即能够调度 php-cgi 进程的程序。并提供了进程管理的功能。进程包含 master 进程和 worker 进程两种进程。master 进程只有一个,负责监听端口 (默认 9000),接收来自 WebServer 的请求,而 worker 进程则一般有多个 (具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。

FastCGI 好在哪里?#

Fastcgi 则会先 fork 一个 master,解析配置文件,初始化执行环境,然后再 fork 多个 worker。当请求过来时,master 会传递给一个 worker,然后立即可以接受下一个请求。这样就避免了重复的劳动,效率自然是高。而且当 worker 不够用时,master 可以根据配置预先启动几个 worker 等着;当然空闲 worker 太多时,也会停掉一些,这样就提高了性能,也节约了资源。这就是 Fastcgi 的对进程的管理。大多数 Fastcgi 实现都会维护一个进程池。注:swoole 作为 httpserver,实际上也是类似这样的工作方式。

我们以用户访问 index.php 为,服务器环境为 LNMP:#

1、用户请求 index.php 时,首先到 Nginx
2、Nginx 流程步骤:
(1)根据配置查找路由
(2)加载 nginx 的 fast-cgi 模块 (FastCGI 的 Client), 将根据 fastcgi.conf 文件中 fastcgi_* 配置参数值也一并加入转发任务中
(3)根据 nginx.conf 文件 fastcgi_pass 配置将请求转发到 127.0.0.1:9000。
3、PHP-FPM 操作:
(1)PHP-FPM 的 master 进程监听 9000 端口。
(2)收到请求后调用子进程来处理逻辑,PHP 解释器解释 PHP 语法并返回给 Nginx。
4、Nginx 操作:
将响应返回给用户

php 代码解释过程#

Php 总共三个模块:
a.PHP 内核:用来处理请求、文件流、错误处理等相关操作
b.zend 引擎:用以将源文件转换成机器语言,然后在虚拟机上运行它
c. 扩展层:是一组函数、类库和流。PHP 使用它们来执行一些特定的操作

比如:我们需要 mysqli 扩展来连接 mysql 数据库;当 zend 执行程序可能会需要连接若干扩展,这是 zend 引擎将控制器交给扩展,等处理完特定任务后再返还,最后 zend 引擎将运行结果返回给 PHP 内核,它再将结果传送给 SAPI 层,最后输出到浏览器上。
PHP 的核心架构如下图:

PHP 只是

a.zend 引擎:zend 引擎整体用纯 C 实现,是 PHP 的内核部分,它将 PHP 代码翻译(词法,语法解析等一系列编译过程)为可执行 opcode 的处理并实现相应的处理方法,实现了基本的数据结构(如 hashtable、oo),内存分配及管理,提供了相应的 api 方法供外部调用,是一切的核心,所有的外围功能均是围绕 zend 实现
b.Extensions:围绕 zend 引擎,extensions 通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如 array 系列)、标准库等都是通过 extensions 来实现。用户也可以根据自己的需要实现自己的 extensions 以达到功能扩展、性能优化等目的。
c.sapi:sapi 全称是 server application programming interface。也就是服务端应用编程接口,sapi 通过一系列钩子函数,使得 PHP 可以和外围交互数据,这是 PHP 非常优雅和成功的设计,通过 sapi 成功的将 PHP 本身和上层应用解耦隔离,PHP 可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式
d. 上层应用:这就是我们平时编写的 PHP 程序,通过不同的 sapi 方式得到各种各样的应用模式,如通过 webserver 实现 web 应用、在命令行下以脚本方式运行等等。
如果 PHP 是一辆车,那么车的框架就是 PHP 本身,Zend 是车的引擎(发动机),Ext 下面的各种组件就是车的轮子,Sapi 可以看做是公路,车可以跑在不同类型的公路上,而一次 PHP 程序的执行就是汽车跑在公路上。因此,我们需要:性能优异的引擎 + 合适的车轮 + 正确的跑道。

如前所述,Sapi 通过通过一系列的接口,使得外部应用可以和 PHP 交换数据并可以根据不同应用特点实现特定的处理方法,我们常见的一些 sapi 有:
apache2handler:这是以 apache 作为 webserver,采用 mod_PHP 模式运行时候的处理方式,也是现在应用最广泛的一种。
cgi:这是 webserver 和 PHP 直接的另一种交互方式,也就是大名鼎鼎的 fastcgi 协议,在最近今年 fastcgi+PHP 得到越来越多的应用,也是异步 webserver 所唯一支持的方式。
cli:命令行调用的应用模式

PHP 执行这段代码会经过如下 4 个步骤 (确切的来说,应该是 PHP 的语言引擎 Zend)
Scanning (Lexing) , 将 PHP 代码转换为语言片段 (Tokens)
Parsing, 将 Tokens 转换成简单而有意义的表达式
Compilation, 将表达式编译成 Opocdes
Execution, 顺次执行 Opcodes,每次一条,从而实现 PHP 脚本的功能。

PHP 的抽象类、接口类的区别和选择#

1、对接口的使用是通过关键字 implements。对抽象类的使用是通过关键字 extends。当然接口也可以通过关键字 extends 继承。
2、接口中不可以声明成员变量(包括类静态变量),但是可以声明类常量。抽象类中可以声明各种类型成员变量,实现数据的封装。(另 Java 接口中的成员变量都要声明为 public static final 类型)
3、接口没有构造函数,抽象类可以有构造函数。
4、接口中的方法默认都是 public 类型的,而抽象类中的方法可以使用 private,protected,public 来修饰。
5、一个类可以同时实现多个接口,但一个类只能继承于一个抽象类。
如果要创建一个模型,这个模型将由一些紧密相关的对象采用,就可以使用抽象类。如果要创建将由一些不相关对象采用的功能,就使用接口。
如果必须从多个来源继承行为,就使用接口。
如果知道所有类都会共享一个公共的行为实现,就使用抽象类,并在其中实现该行为。
抽象类中不一定都是抽象的方法,也可以有具体实现的方法,这样就可以把大家公用的方法提升到抽象类中,然后具体的方法可以留给子类自己实现(此处经典的应用,模板方法设计模式)。所以抽象类可以更好的实现代码的复用
接口和抽象类的概念不一样。这个可以理解为接口是对动作的抽象,抽象类是对根源的抽象(即对本质的抽象与其他类的本质不同)。

PHP 的垃圾收集机制是怎样的#

PHP 可以自动进行内存管理,清除不再需要的对象。
PHP 使用了引用计数 (reference counting) 这种单纯的垃圾回收 (garbage collection) 机制。每个对象都内含一个引用计数器,每个 reference 连接到对象,计数器加 1。当 reference 离开生存空间或被设为 NULL,计数器减 1。当某个对象的引用计数器为零时,PHP 知道你将不再需要使用这个对象,释放其所占的内存空间。

本作品采用《CC 协议》,转载必须注明作者和本文链接