1. PHP的垃圾收集机制
PHP可以自动进行内存管理,清除不再需要的对象。PHP使用了引用计数(reference counting)这种单纯的垃圾回收(garbage collection)机制。
每个对象都内含一个引用计数器,每个reference连接到对象,计数器加1。当reference离开生存空间或被设为NULL,计数器减1。当某个对象的引用计数器为零时,PHP知道你将不再需要使用这个对象,释放其所占的内存空间。
2. php 数组底层实现原理
(1) 实现原理
底层实现是通过散列表(hash table) + 双向链表(解决hash冲突)
-
hashtable:将不同的关键字(key)通过映射函数计算得到散列值(Bucket->h) 从而直接索引到对应的Bucket
-
hash表保存当前循环的指针,所以foreach 比for更快(pInternalPointer)
-
Bucket:保存数组元素的key和value,以及散列值h
(2) 如何保证有序性
-
散列函数和元素数组(Bucket)中间添加一层大小和存储元素数组相同的映射表。
-
用于存储元素在实际存储数组中的下标
-
元素按照映射表的先后顺序插入实际存储数组中
-
映射表只是原理上的思路,实际上并不会有实际的映射表,而是初始化的时候分配Bucket内存的同时,还会分配相同数量的 uint32_t 大小的空间,然后将 arData 偏移到存储元素数组的位置。
(3) 解决hash重复(php使用的链表法)
-
链表法:不同关键字指向同一个单元时,使用链表保存关键字(遍历链表匹配key)
-
开放寻址法:当关键字指向已经存在数据的单元的时候,继续寻找其他单元,直到找到可用单元(占用其他单元位置,更容易出现hash冲突,性能下降)
(4) 基础知识
-
链表:队列、栈、双向链表、
-
链表 :元素 + 指向下一元素的指针
-
双向链表:指向上一元素的指针 + 元素 + 指向下一元素的指针
3. 常见的 PHP 安全性攻击
(1) Sql注入
使用mysql_real_escape_string()过滤数据 使用预处理语句并绑定变量 参数化SQL:是指在设计与数据库链接并访问数据时,在需要填入数值或数据的地方,使用参数 (Parameter) 来给值,用@或?来表示参数
(2) Xss
跨站点脚本攻击,由用户输入一些数据到你的网站,其中包括客户端脚本(通常JavaScript)。如果你没有过滤就输出数据到另一个web页面,这个脚本将被执行
防止:为了防止XSS攻击,使用PHP的htmlentities()函数过滤再输出到浏览器。
(3) Csrf
跨站点请求伪造,是指一个页面发出的请求,看起来就像是网站的信任用户,但是是伪造的
防止:一般来说,确保用户来自你的表单,并且匹配每一个你发送出去的表单。有两点一定要记住:对用户会话采用适当的安全措施,例如:给每一个会话更新id和用户使用SSL。生成另一个一次性的令牌并将其嵌入表单,保存在会话中(一个会话变量),在提交时检查它。如laravel中的 _token
4. Nginx与PHP的交互
为了调用CGI程序,还需要一个FastCGI的wrapper(wrapper可以理解为用于启动另一个程序的程序),这个wrapper绑定在某个固定socket上,如端口或者文件socket。当Nginx将CGI请求发送给这个socket的时候,通过FastCGI接口,wrapper接收到请求,然后Fork(派生)出一个新的线程,这个线程调用解释器或者外部程序处理脚本并读取返回数据;接着,wrapper再将返回的数据通过FastCGI接口,沿着固定的socket传递给Nginx;最后,Nginx将返回的数据(html页面或者图片)发送给客户端。这就是Nginx+FastCGI的整个运作过程
5. TCP 和 UDP 的特点和区别
- 都是属于传输层协议
- TCP面向连接,所以只能一对一,面向字节流传输,数据可靠,不丢失,全双工通信
- UDP(根据TCP特点反记),无连接,支持一对一,一对多,多对多,面向报文传输,首部开销小,数据不一定可靠(可能会丢包)但是速度更快
6. HTTP 状态码
(1) 状态码分类
- 1xx:信息,服务器收到请求,需要请求者继续操作
- 2xx:成功
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务端错误
(2) 常用状态码
- 200:请求成功
- 301:永久重定向
- 302:临时移动
- 400 bad request:客户端请求语法错误
- 401 unauthorized:客户端没有权限
- 403 forbidden:服务器拒绝客户端请求
- 404 not found:客户端请求资源不存在
- 500 Internal Server Eerro:服务器内部错误
- 502 bad gateway:网关错误,代理服务器后面的真实服务器节点配置出了问题或者已经挂掉了(比如:nginx与fastcgi即PHP进程配合的不恰当)
- 503 Service Unavailable 超载或系统维护
- 504 Gateway timeout:网关超时,代理服务器后面的真实服务器已经过载,它要处理的请求报文实在太多
6.程序、进程、线程、 协程
程序
编译好的二进制文件,不占用资源。
进程
活跃着的程序,占用资源,是操作系统的基本单位。表示一个程序的上下文执行活动(打开、执行、保存…),是系统资源分配的最小单位,一个程序至少有一个进程。
线程
进程的执行单位,与进程共享资源。
一个进程至少有一个线程。进程执行程序时候的最小调度单位(执行a,执行b…),是CPU调度的最小单位.进程相当于一个容器,而线程而是运行在容器里面的,因此对于容器内的东西,线程是共同享有的,因此线程间的通信可以直接通过全局变量进行通信,共享意味着竞争,导致数据不安全,为了保护内存空间的数据安全,引入”互斥锁”。
协程
协程是一种用户态的轻量级线程,协程的调度完全由用户控制。
迭代器最基本的规定了对象可以通过next返回下一个值,而不是像数组,列表一样一次性返回。
生成器: 使用 yield 关键字的函数,生成器也可通过next返回下一个值。
多线程比,协程有何优势?
极高的执行效率:因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显;
不需要多线程的锁机制:因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
7.swoole如何提升性能
1.进程常驻内存:
swoole本⾝是进程常驻内存,在进程启动的时候就将PHP框架等代码读取并编译完成,不需要每次启动的时候都执⾏编译步骤,⼤⼤降低了脚本的运⾏时间;
2.连接池
php-fpm的模式php因为每次请求结束时都会销毁所有资源,因此⽆法使⽤连接池;⽽基于swoole的进程常驻内存模式,可以通过连接池的⽅式来加速程序,使⽤连接池既可以降低程序的响应时间,⼜可以有效保护后端资源。
3.可以使⽤协程处理异步IO
当开发中需要去请求多处的数据,⽽每⼀块的数据单独请求都要花较长时间,常规的php-fpm是阻塞式运⾏,⽆法对这类型的数据处理进⾏加速;⽽基于swoole的程序,可以将这类的业务并⾏化处理,并⾏去请求后端的数据源,能够⼤⼤优化了此类业务的运⾏时间。
8. swoole⾥的协程是什么,怎么⽤?为什么协程可以提⾼并发?
协程是通过协作⽽不是抢占的⽅式来进⾏切换,它创建和切换对内存等资源⽐线程⼩的多(可以理解为更⼩的线程);
协程的使⽤是通过Swoole\Coroutine或者Co\命名空间短命名简化类名来创建;
协程可以异步处理任务,⽀持并发,并且资源消耗⼩。
9.⽤了swoole以后,会不会发⽣内存泄漏?如果发⽣了怎么解决?
swoole由于是常驻内存,⼀旦资源加载进⼊后,会⼀直存在于内存中。对于局部变量,swoole会在回调函数结束后⾃动释放;对于全局变量(lobal声明的变量,static声明的对象属性或者函数内的静态变量和超全局变量),swoole不会⾃动释放;因此操作不好会发⽣内存泄漏。
网友评论