PHP 面试要点

简单做一下自我介绍? 介绍一下三年内最得意的项目?

操作系统

  • IO 多路复用是什么?有哪些 api?

  • select 和 epoll 的区别?水平触发和边缘触发的区别是啥?使用的时候需要注意什么?

    • select:fd_setsize有限制1024,fd基于数组存储,每次调用都要将fd集合从用户态拷贝到内核态,每次调用都需要在内核中遍历所有的fd

    • poll:本质和select没有区别,fd_size不限制,原因是fd是基于链表存储的

    • epoll:fd_size不限制,fd基于红黑树存储,同时每一次通过epoll_ctl来将fd加入内核中

  • epoll 储存描述符的数据结构是什么?

  • select 有描述符限制吗?是多少?

  • 进程 / 线程 / 协程区别?go 和 swoole 的协程实现有啥区别?(分配资源的基本单位 / 运行和调度的基本单位 / 用户线程,M:N 模型和 N:1 模型)

计算机网络

  • TCP 三次握手的流程

  • 客户端发送一个 SYN 标志位置 1 的包,指明客户端要连接服务器端的接口,发送完毕后,客户端进入 SYN_SEND 状态

  • 服务器发回确认包 (ACK) 应答。即 SYN 标志位和 ACK 标志位均为1。服务器端选择自己 ISN 序列号,放到 Seq 域里,同时将确认序号(Acknowledgement Number)设置为客户的 ISN 加1,即X+1。 发送完毕后,服务器端进入 SYN_RCVD 状态。

  • 客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1

  • TCP 三次握手和四次挥手,为什么三次握手,为什么四次挥手 在Tcp连接中,服务端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是分两次发送的。因为在B端接收到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了

  • 一次完整的 HTTP 请求(从浏览器输入 www.baidu.com 到加载出页面发生了什么) 1. dns 解析 ip port 2. 建立 tcp 连接 3. 发送 HTTP 报文 4. 接收 HTTP 报文 5. 浏览器解析显示 6. 断开 tcp 连接

  • HTTP 协议包括哪些请求? 1. GET:请求读取由URL所标志的信息。 2. POST:给服务器添加信息(如注释)。 3. PUT:在给定的URL下存储一个文档。 4. DELETE:删除给定的URL所标志的资源。

  • GET 和 POST 区别 1. GET在浏览器回退时是无害的,而POST会再次提交请求。 2. GET产生的URL地址可以被Bookmark,而POST不可以。 3. GET请求会被浏览器主动cache,而POST不会,除非手动设置。 4. GET请求只能进行url编码,而POST支持多种编码方式application/x-www-form-urlencoded,multipart/form-data,application/json,text/xml 5. GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。 6. GET请求在URL中传送的参数是有长度限制的,而POST没有。 7. 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。 8. GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。 9. GET参数通过URL传递,POST放在Request body中。 10. GET产生一个TCP数据包,POST产生两个TCP数据包。GET请求将http header和data一起发送,POST请求先发header,再发送data,返回数据

  • Cookie存在哪

    • 如果设置了过期时间,Cookie存在硬盘里

    • 如果没有设置过期时间,Cookie存在内存里(会随着浏览器的关闭而消失)

  • Session 和 Cookie 的区别,禁用 Cookie 后怎么办 1. COOKIE保存在客户端,而SESSION则保存在服务器端 2. 从安全性来讲,SESSION的安全性更高 3. 从保存内容的类型的角度来讲,COOKIE只保存字符串(及能够自动转换成字符串) 4. 从保存内容的大小来看,COOKIE保存的内容是有限的,比较小,而SESSION基本上没有这个限制 5. 从性能的角度来讲,用SESSION的话,对服务器的压力会更大一些 6. SEEION依赖于COOKIE,但如果禁用COOKIE,也可以通过url传递

PHP

  • PHP执行过程

    • 扫描:将index.php内容变成一个个语言片段(token)

    • 解析:将一个个语言片段有意义的表达式

    • 编译:将表达式编译成中间码(opcode)

    • 执行:将中间码一条条的执行

    • 输出:将要输出的内容输出到缓冲区

  • nginx中php-fpm的socket是什么类型。

    • unix socket适合nginx和php-fpm都在一台机器上

    • tcp socket适合nginx和php-fpm不在同一台机器上

  • PHP 的解析方式有哪几种?cgi、fastcgi、php-fpm 区别

    • cgi:公共网关接口,http服务器发起请求,会启动对应的实现了cgi协议的php解析器,php解析器解析php.ini,初始化执行环境,并处理请求,在以cgi规定的格式返回结果,推出进程。

    • fast-cgi:由cgi发展而来,是一种进程池,先启动一个master进程,解析php.ini和初始化执行环境,然后启动多个worker进程,php请求发到master进程,通过master进程分发的到worker进程进行处理

    • php-fpm:fastcgi进程管理器,用于替换php内核的fastcgi大部分附加功能

  • 描述一下 cli 模式下的几个生命周期? 1. 模块初始化阶段 (Module init):即调用每个拓展源码中的的 PHP_MINIT_FUNCTION 中的方法初始化模块,进行一些模块所需变量的申请,内存分配等。 2. 请求初始化阶段 (Request init):即接受到客户端的请求后调用每个拓展的 PHP_RINIT_FUNCTION 中的方法,初始化 PHP 脚本的执行环境。 3. 执行该 PHP 脚本。 4. 请求结束 (Request Shutdown):这时候调用每个拓展的 PHP_RSHUTDOWN_FUNCTION 方法清理请求现场,并且 ZE 开始回收变量和内存 5. 关闭模块 (Module shutdown):Web 服务器退出或者命令行脚本执行完毕退出会调用拓展源码中的 PHP_MSHUTDOWN_FUNCTION 方法

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

  • PHP7 与 PHP5 1. 性能提升:PHP7 比 PHP5.0 性能提升了两倍。 2. 全面一致的 64 位支持。 3. 以前的许多致命错误,现在改成 [抛出异常]。 4. PHP 7.0 比 PHP5.0 移除了一些老的不在支持的 SAPI([服务器端] 应用编程端口)和扩展。 5. PHP 7.0 比 PHP5.0 新增了空接合操作符。 6. PHP 7.0 比 PHP5.0 新增加了结合比较运算符。 7. PHP 7.0 比 PHP5.0 新增加了函数的返回类型声明。 8. PHP 7.0 比 PHP5.0 新增加了标量类型声明。 9. PHP 7.0 比 PHP5.0 新增加匿名类。

  • GC(垃圾回收) 的出现是为了解决什么问题?什么时候会触发 GC?说下大概流程 1. PHP 5.3 版本之前都是采用引用计数的方式管理内存 2. PHP 所有的变量存在一个叫 zval 的变量容器中,当变量被引用的时候,引用计数会+1,变量引用计数变为0时,PHP 将在内存中销毁这个变量 3. 引用计数中的循环引用,引用计数不会消减为 0,就会导致内存泄露 4. 在 5.3 版本之后,做了这些优化: 1. 并不是每次引用计数减少时都进入回收周期,只有根缓冲区满额后在开始垃圾回收; 2. 可以解决循环引用问题; 3. 可以总将内存泄露保持在一个阈值以下。

  • 如何解决 PHP 内存溢出问题 1. 增大 PHP 脚本的内存分配 2. 变量引用之后及时销毁 3. 将数据分批处理

  • php-fpm 运行机制?(master 管理,worker 循环 accept)

  • php-fpm 模式下,kill -9 master-pid,会怎么样?kill matser-pid 呢?(信号机制)

  • 内存分配流程?为什么要这么设计?

  • php 里的数组是怎么实现的?(这里要注意下 php5 和 php7 实现的区别,优化了非常多)

  • nginx 和 php-fpm 的通信机制?fast-cgi 和 cgi 区别?

  • php-fpm 创建 worker 进程的规则是什么?不同场景下怎么选择?

  • php 和 mysql 的通信机制?长链接和短链接啥区别?怎么实现的?连接池要怎么实现?

  • swoole 协程的原理?(遇到阻塞时引发 php 栈和 c 栈的切换,细节可以参考下我的文章)

  • 依赖注入是什么?如何实现的?能解决什么问题?(代码层面不再依赖具体实现,解耦)

mysql

  • MySQL主要的存储引擎MyISAM和InnoDB的不同之处?

    解答思路:可以从五个方向去介绍。

    事务的支持不同(InnoDB支持事务、MyISAM不支持事务);

    锁粒度(InnoDB行锁应用、MyISAM表锁);

    存储空间(InnoDB既缓存索引文件,又缓存数据文件,MyISAM只能缓存索引文件);

    存储结构(MyISAM:数据文件的扩展名为.MYD myData,索引文件的扩展名是.MYI myIndex;InnoDB:所有的表都保存在同一个数据文件里面,即.Ibd);

    统计记录行数(MyISAM:保存有表的总行数,select count() from table会直接取出该值;InnoDB:没有保存表的总行数,select count() from table会遍历整个表,消耗相当大)。

  • Mysql 主从同步了解吗? 1. MySQL之间的数据复制的基础是二进制日志文件binlog 2. 台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中, 3. 其它数据库作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化, 4. 如果发现master二进制日志文件发生变化,则会把变化复制到自己的中继日志中,然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据的一致性,也就实现了主从复制 (主服务器把数据更新记录到二进制日志中,从服务器通过I/O thread向主库发起binlog请求,主服务器通过I/O dump thread把二进制日志传递给从库,从库通过I/O thread记录到自己的中继日志中。然后通过SQL thread应用中继日志中SQL的内容。)

    如何查看机器运行的建康指标,如:CPU的LOAD和使用率,内存使用率,磁盘使用率,IOWAIT等,除此之外还有那些重要指标可以用来分析特定场景问题?

    yum install iotop iftop iostat htop 安装一系列工具 htop是top命令的加强版,可以看到cpu,内存,执行的进程等信息

  • iftop 是监控网卡的

  • iotop 是监控io的

  • free -m 监控可用内存

  • uptime 查看当前系统负载

  • df -hl 查看磁盘

  • 安装smart 工具yum install -y smartmontools,查看磁盘的smart信息smartctl -a /dev/sda

  • 查看cpu信息cat /proc/cpuinfo

  • 查看内存信息 cat /proc/meminfo

    nginx

  • LVS 和 Nginx 分别作用在 osi 哪一层?

  • 负载均衡算法 1. 轮询(默认)每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。 2. Weight 指定轮询几率,weight 和访问比率成正比, 用于后端服务器性能不均的情况。 3. ip_hash 每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 共享的问题。 4. fair(第三方)按后端服务器的响应时间来分配请求,响应时间短的优先分配。 5. url_hash(第三方)

安全防范

  • CSRF 是什么?如何防范? 1. CSRF(Cross-site request forgery)通常被叫做「跨站请求伪造」,可以这么理解:攻击者盗用用户身份,从而欺骗服务器,来完成攻击请求。 2. 防范措施: 1. 使用验证码 2. 给每一个请求添加令牌 token 并验证 只使用json api(js 发起ajax请求是限制跨域的) 禁用cross-origin(只允许options、head、get方法跨域请求) 检验referer头部 GET总是幂等 避免使用POST 不要复写方法 不要兼容旧浏览器 CSRF Tokens

  • XSS 是什么?如何防范? 1. XSS(Cross Site Scripting),跨站脚本攻击,攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页之时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。 2. 防止 XSS 攻击的方式有很多,其核心的本质是:永远不要相信用户的输入数据,始终保持对用户数据的过滤 3. 将重要的cookie标记为http only,这样的话Javascript 中的document.cookie语句就不能获取到cookie了

  • 什么是 SQL 注入?SQL注入产生的原因?如何防范? 1. SQL注入产生的原因: 1. 程序开发过程中不注意规范书写SQL语句和对特殊字符进行过滤,导致客户端可以通过全局变量POST和GET提交一些sql语句正常执行 2. 防范措施 1. 保持对用户数据的过滤(严格检查输入变量的类型和格式) 2. 过滤和转义特殊字符比如addslashes()函数 3. 利用mysql的预编译机制

1、为什么使用redis (一)性能 我们在碰到需要执行耗时特别久,且结果不频繁变动的SQL,就特别适合将运行结果放入缓存。这样,后面的请求就去缓存中读取,使得请求能够迅速响应。 (二)并发 在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问数据库。 2.使用redis有什么缺点 (一)缓存和数据库双写一致性问题 (二)缓存雪崩问题 (三)缓存击穿问题 (四)缓存的并发竞争问题 3、单线程的redis为什么这么快 (一)纯内存操作 (二)单线程操作,避免了频繁的上下文切换 (三)采用了非阻塞I/O多路复用机制 参照上图,简单来说,就是。我们的redis-client在操作的时候,会产生具有不同事件类型的socket。在服务端,有一段I/0多路复用程序,将其置入队列之中。然后,文件事件分派器,依次去队列中取,转发到不同的事件处理器中。 4、redis的数据类型,以及每种数据类型的使用场景 回答:一共五种 (一)String 这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。 (二)hash 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。 (三)list 使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。本人还用一个场景,很合适—取行情信息。就也是个生产者和消费者的场景。LIST可以很好的完成排队,先进先出的原则。 (四)set 因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。 (五)sorted set sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。

  • Redis 如何实现持久化

    1. RDB 持久化,将 Redis 在内存中的的状态保存到硬盘中,相当于备份数据库状态。

    2. AOF 持久化(Append-Only-File),AOF 持久化是通过保存 Redis 服务器锁执行的写状态来记录数据库的。相当于备份数据库接收到的命令,所有被写入 AOF 的命令都是以 Redis 的协议格式来保存的

Last updated

Was this helpful?