简述php的垃圾收集机制
答案:php中的变量存储在变量容器zval中,zval中除了存储变量类型和值外,还有is_ref和refcount字段。refcount表示指向变量的元素个数,is_ref表示变量是否有别名。如果refcount为0时,就回收该变量容器。如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区。当缓冲区达到最大值后,回收算循环遍历zval,判断其是否为垃圾,并进行释放处理。
PHP的内核组成
php总共包括3个模块:php内核,zend引擎,PHP扩展层
1.1 php内核:用于处理请求,文件流,错误处理等相关处理。
1.2. zend引擎:将源文件转换成机器语言,然后在zend 虚拟机上运行
zend 整体由两个部分组成:
编译器:负责将php代码编译为可执行的opcodes(中间码/字节码)
执行器:负责将执行编译器输出的opcodes,也就是执行php脚本中编写的代码逻辑
1.3.扩展
扩展层是一组函数、类库和流,php使用它们来执行一些特定的操作,比如安装php_openssl扩展来使用 open ssl函数
php性能优化
APC与Opcache都是字节码缓存也就是,PHP在被编译的时候,首先会把php代码转换为字节码,字节码然后被执行。
php文件第二次执行时,同样还是会重新转换为字节码,但是很多时候,文件内容几乎是一样的,比如静态HTML文件,生成后内容许久都不会改变,用户访问请求直接由服务器读取响应给客户端浏览器。都不用经过PHP进行解析构建了。
PHP APC提供两种缓存功能,即缓存Opcode(目标文件),我们称之为apc_compiler_cache。同时它还提供一些接口用于PHP开发人员将用户数据驻留在内存中,我们称之为apc_user_cache。
内存中的字节码数据,可以直接缓存进行二次编译。这样程序就会快一些,cpu的消耗也少了。
(这里字节码 就是 opcode)
cgi、fast-cgi协议
cgi的历史:早期的webserver只处理html等静态文件,但是随着技术的发展,出现了像php等动态语言。
webserver处理不了了,怎么办呢?那就交给php解释器来处理吧! 交给php解释器处理很好,但是,php解释器如何与webserver进行通信呢?
为了解决不同的语言解释器(如php、python解释器)与webserver的通信,于是出现了cgi协议。只要你按照cgi协议去编写程序,就能实现语言解释器与webserver的通信。如php-cgi程序。
fast-cgi的改进
有了cgi协议,解决了php解释器与webserver通信的问题,webserver终于可以处理动态语言了。但是,webserver每收到一个请求,都会去fork一个cgi进程,请求结束再kill掉这个进程。这样有10000个请求,就需要fork、kill php-cgi进程10000次。
有没有发现很浪费资源?于是,出现了cgi的改良版本,fast-cgi。fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率。
PHP-FPM管理的方式是一个master主进程,多个pool进程池,一个pool进程池多个worker子进程。其中每个进程池监听一个socket
php-fpm是什么
php-fpm即php-Fastcgi Process Manager.
php-fpm是 FastCGI 的实现,并提供了进程管理的功能。
进程包含 master 进程和 worker 进程两种进程。
master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。
php-fpm 与 swoole 之间的区别
PHP-FPM
1.Master 主进程 / Worker 多进程模式。
2.启动 Master,通过 FastCGI 协议监听来自 Nginx 传输的请求。
3.每个 Worker 进程只对应一个连接,用于执行完整的 PHP 代码。
4.PHP 代码执行完毕,占用的内存会全部销毁,下一次请求需要重新再进行初始化等各种繁琐的操作。
5.只用于 HTTP Server。
Swoole
1.Master 主进程(由多个 Reactor 线程组成)/ Worker 多进程(或多线程)模式
2.启动 Master,初始化 PHP 代码,由 Reactor 监听 Socket 句柄的事件变化。
3.Reactor 主线程负责子多线程的均衡问题,Manager 进程管理 Worker 多进程,包括 TaskWorker 的进程。
4.每个 Worker 接受来自 Reactor 的请求,只需要执行回调函数部分的 PHP 代码。
5.只在 Master 启动时执行一遍 PHP 初始化代码,Master 进入监听状态,并不会结束进程。
6.不仅可以用于 HTTP Server,还可以建立 TCP 连接、WebSocket 连接。
PHP7的新特性?重点
性能提升 ----
1、变量存储字节减小,减少内存占用,提升变量操作速度
2、改善数组结构,数组元素和hash映射表被分配在同一块内存里,降低了内存占用、提升了 cpu 缓存命中率
3、改进了函数的调用机制,通过优化参数传递的环节,减少了一些指令,提高执行效率
对于大流量的网站,采用什么样的方法来解决访问量问题?
1.负载均衡(分流)微服务架构(服务拆分)读写分离(数据库主从)
2.静态页面 缓存
3.图片服务器分离,cdn加速
4.开启opcache,提高代码执行效率
1、HTML静态化
效率最高、消耗最小的就是纯静态化的html页面,所以我们尽可能使我们的 网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。
2、图片服务器分离
把图片单独存储,尽量减少图片等大流量的开销,可以放在一些相关的平台上,如七牛
3、数据库集群和库表散列及缓存
数据库的并发连接为100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如memcache、redis。
4、cdn加速
CDN加速意思就是在用户和我们的服务器之间加一个缓存机制,通过这个缓存机制动态获取IP地址根据地理位置,让用户到最近的服务器访问静态资源。
5、负载均衡:
Apache的最大并发连接为1500,只能增加服务器,可以从硬件上着手,如F5服务器。当然硬件的成本比较高,我们往往从软件方面着手。
PHP限流方案
1.令牌桶限流方案(nginx可以实现,hyperf框架也支持)
算法:以固定的速度生产令牌,设置令牌上限。每个请求获取令牌token即可正常访问,获取不到即为拒绝访问。
比如每秒产生5个,桶令牌上限为20个,每次请求获取并消耗1个令牌,获取不到则拒绝访问。