1.php工作原理
PHP的核心架构如下图:
从图上可以看出,PHP从下到上是一个4层体系:
- Zend引擎:Zend整体用纯C实现,是PHP的内核部分,它将PHP代码翻译(词法、语法解析等一系列编译过程)为可执行opcode的处理并实现相应的处理方法、实现了基本的数据结构(如hashtable、oo)、内存分配及管理、提供了相应的api方法供外部调用,是一切的核心,所有的外围功能均围绕Zend实现。
- Extensions:围绕着Zend引擎,extensions通过组件式的方式提供各种基础服务,我们常见的各种内置函数(如array系列)、标准库等都是通过extension来实现,用户也可以根据需要实现自己的extension以达到功能扩展、性能优化等目的(如贴吧正在使用的PHP中间层、富文本解析就是extension的典型应用)。
- Sapi:Sapi全称是Server Application Programming Interface,也就是服务端应用编程接口,Sapi通过一系列钩子函数,使得PHP可以和外围交互数据,这是PHP非常优雅和成功的一个设计,通过sapi成功的将PHP本身和上层应用解耦隔离,PHP可以不再考虑如何针对不同应用进行兼容,而应用本身也可以针对自己的特点实现不同的处理方式。
- 上层应用:这就是我们平时编写的PHP程序,通过不同的sapi方式得到各种各样的应用模式,如通过webserver实现web应用、在命令行下以脚本方式运行等等。
如果PHP是一辆车,那么车的框架就是PHP本身,Zend是车的引擎(发动机),Ext下面的各种组件就是车的轮子,Sapi可以看做是公路,车可以跑在不同类型的公路上,而一次PHP程序的执行就是汽车跑在公路上。因此,我们需要:性能优异的引擎+合适的车轮+正确的跑道。
3. Sapi
如前所述,Sapi通过通过一系列的接口,使得外部应用可以和PHP交换数据并可以根据不同应用特点实现特定的处理方法,我们常见的一些sapi有:
- CGI(通用网关接口/ Common Gateway Interface)
- FastCGI(常驻型CGI / Long-Live CGI)
- CLI(命令行运行 / Command Line Interface)
- Web模块模式(Apache等Web服务器运行的模式)
- ISAPI(Internet Server Application Program Interface)
4. PHP的执行流程&opcode
我们先来看看PHP代码的执行所经过的流程。
从图上可以看到,PHP实现了一个典型的动态语言执行过程:拿到一段代码后,经过词法解析、语法解析等阶段后,源程序会被翻译成一个个指令(opcodes),然后ZEND虚拟机顺次执行这些指令完成操作。PHP本身是用C实现的,因此最终调用的也都是C的函数,实际上,我们可以把PHP看做是一个C开发的软件。
PHP的执行的核心是翻译出来的一条一条指令,也即opcode。
Opcode是PHP程序执行的最基本单位。一个opcode由两个参数(op1,op2)、返回值和处理函数组成。PHP程序最终被翻译为一组opcode处理函数的顺序执行。
2.php的五大运行模式
3.thinkphp工作原理
http://www.thinkphp.cn/topic/35803.html
4.DNS服务器是干什么的?
DNS 是域名系统 (Domain Name System) 的缩写,是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。。
5.索引的数据结构,工作原理?索引种类,唯一索引是什么意思?
6.php-fpm是什么?它是怎么工作的?跟cgi的区别是什么?
php-fpm(php-FastCGI Process Manager)是基于php的FastCGI的进程管理器。
php-fpm有两种进程,master和worker。master进程只有一个,而worker进程有多个。
php-fpm有独立的进程池pool来运行CGI,每个pool有多个worker进程。
每个worker进程都内置php解释器,并且进程常驻后台,支持prefork动态增加。
每个worker进程支持在运行时编译脚本并在内存中缓存生成的opcode来提升性能。
每个worker进程都支持配置响应指定请求数后自动重启,master进程会重启挂掉的worker进程。
每个worker进程能保持一个到MySQL/memcache/redis的持久连接,实现“”连接池,避免重复连接,对程序透明。
使用数据库持久连接时应该设置固定数量的worker进程数,不要使用动态的prefork模式。
master进程并不接收和分发请求,而是worker进程直接accept请求后poll处理。
php支持epoll模型,监听时epoll,accept后poll(下面会详细解释epoll模型)
master进程不断调用epoll_wait和getsocket用来异步处理信号事件和定时器事件。
master进程并不处理请求,而是worker直接处理。
如果worker进程不够用,master进程会prefork更多进程,如果prefork达到了pm.max_children(在php-fpm.conf文件中设置)的上限,worker进程又全部繁忙,这时master进程会把请求挂起到连接队列backlog里(默认是511)
1个php-fpm只能在同一时刻处理一个请求
MySQL的最大连接数max_connections默认是151,所以只要php-fpm工作进程数不超过151,就不会出现连接不上MySQL的情况,而且正常情况下,也不需要开启那么多的php-fpm进程,比如4个php-fpm进程就能跑满4个核心的CPU,开40个进程就毫无意义,只会占用更多的内存,造成更多的CPU上下文切换,性能反而更差,为了减少每个请求都重复建立和释放连接的开销,可以开启持久连接。一个php-fpm进程保持一个到MySQL的长连接,实现透明的"连接池"
nginx和php-fpm分开,其实是很好的解耦,php-fpm专门负责php请求,一个页面对应一个php请求,页面中所有的静态资源的请求都是由nginx来处理,这样就实现了动静分离,而nginx最擅长的就是处理高并发。
php-fpm是一个多进程的FastCGI服务,类似Apache的prefork进程模型。对于只处理php请求来说,这种模型是很高效很稳定的,不像Apache,一个页面,要处理多个请求,包括图片,样式表,js脚本php脚本等。
工作流程:
1)当WebServer启动的时候,加载php-fpm.
2)php-fpm进行自身初始化,并生成很多CGI解释器php-cgi.exe,等待Webserver的连接。
3)当用户有一个请求,WebServer会连接其中一个解释器,传递环境变量和标准给php-cgi.exe
4)当php-cgi.exe处理完请求以后,将标准输出和错误信息从同一连接返回给WebServer,然后连接关闭,继续等待下一次请求。
跟CGI的区别:
1)CGI是fork-and-execute模式,每有一个用户请求就会fork一个进程来处理请求。
FastCGI是预先启动很多个子进程去等待请求。
2)CGI每一个WEB请求都要重新解析php.ini文件,重新加载dll库, 初始化全部数据结构。
FastCGI上面那些只需要在进程管理器启动的时候加载一次,数据库连接将持续工作。
7.二分法的原理
原理是折半查找,不断的缩小关键字所在的范围,直到找到关键字,或者找不到退出程序。
8.有一个数据表,字段id,q_id,pv,time,求最近一周内浏览量最高的pv
select max(pv),q_id,pv from question where time between ".strtotime('-7 days')." and ".time()." group by q_id;
include('dump.php');
$con = mysql_connect('localhost','root','root');
mysql_select_db('test',$con);
$sql = "select max(pv),q_id,pv from question where time between ".strtotime('-7 days')." and ".time()." group by q_id";
$res = mysql_query($sql);
while($row = mysql_fetch_array($res,MYSQL_ASSOC)){
$result[] = $row;
}
dump($result);die;
输出结果:
9.TCP和UDP的区别。
区别:
1)TCP是面向连接的(三次握手);UDP是无连接的。
2)TCP对系统资源要求比较高(首部开销20字节);UDP要求相对较低(首部开销8个字节)。
3)TCP可靠,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,但不保证可靠交付。
4)TCP面向字节流;UDP面向报文
5)TCP连接是点对点的;UDP支持一对一,一对多,多对一和多对多的交互通信
6)TCP传输速度较慢;UDP较快
7)TCP适合传输大量数据;UDP适合少量数据
优缺点:
TCP 优点:
可靠,稳定 TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、 重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。
缺点:
慢,效率低,占用系统资源高,易被攻击 TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时, 确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连 接都会占用系统的CPU、内存等硬件资源。 而且,因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用, 实现DOS、DDOS、CC等攻击。
UDP优点:
快,比TCP稍安全 UDP没有TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所 以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。
缺点:
不可靠,不稳定 因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。
10.为什么lnmp比lamp在高并发方面表现要好?
主要是因为Apache和nginx的模型不一样:
一. select 模型(apache的常用)
1. 最大并发数限制,因为一个进程所打开的 FD (文件描述符)是有限制的,由 FD_SETSIZE 设置,默认值是 1024/2048 ,因此 Select 模型的最大并发数就被相应限制了。自己改改这个 FD_SETSIZE ?想法虽好,可是先看看下面吧 …
2. 效率问题, select 每次调用都会线性扫描全部的 FD 集合,这样效率就会呈现线性下降,把 FD_SETSIZE 改大的后果就是,大家都慢慢来,什么?都超时了。
3. 内核 / 用户空间 内存拷贝问题,如何让内核把 FD 消息通知给用户空间呢?在这个问题上 select 采取了内存拷贝方法,在FD非常多的时候,非常的耗费时间。
总结为:1.连接数受限 2.查找配对速度慢 3.数据由内核拷贝到用户态消耗时间
二. Epoll模型的提升(nginx的使用)
再来看看 Epoll 的改进之处吧,其实把 select 的缺点反过来那就是 Epoll 的优点了。
①. Epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048, 一般来说这个数目和系统内存关系很大 ,具体数目可以 cat /proc/sys/fs/file-max 察看。
②. 效率提升, Epoll 最大的优点就在于它只管你“活跃”的连接 ,而跟连接总数无关,因此在实际的网络环境中, Epoll 的效率就会远远高于 select 和 poll 。
③. 内存共享, Epoll 在这点上使用了“共享内存 ”,这个内存拷贝也省略了。
三. Epoll 为什么高效?
Epoll 的高效和其数据结构的设计是密不可分的,这个下面就会提到。
首先回忆一下 select 模型,当有 I/O 事件到来时, select 通知应用程序有事件到了快去处理,而应用程序必须轮询所有的 FD 集合,测试每个 FD 是否有事件发生,并处理事件;代码像下面这样:
1 int res = select(maxfd+1, &readfds, NULL, NULL, 120);
2 if (res > 0)
3 {
4 for (int i = 0; i < MAX_CONNECTION; i++)
5 {
6 if (FD_ISSET(allConnection[i], &readfds))
7 {
8 handleEvent(allConnection[i]);
9 }
10 }
11 }
12 // if(res == 0) handle timeout, res < 0 handle error
Epoll 不仅会告诉应用程序有I/0 事件到来,还会告诉应用程序相关的信息,这些信息是应用程序填充的,因此根据这些信息应用程序就能直接定位到事件,而不必遍历整个FD 集合。类似的代码可能如下所示:
1 int res = epoll_wait(epfd, events, 20, 120);
2 for (int i = 0; i < res;i++)
3 {
4 handleEvent(events[n]);
5 }
Epoll 关键数据结构
前面提到 Epoll 速度快和其数据结构密不可分,其关键数据结构就是:
1 struct epoll_event {
2 __uint32_t events; // Epoll events
3 epoll_data_t data; // User data variable
4 };
5 typedef union epoll_data {
6 void *ptr;
7 int fd;
8 __uint32_t u32;
9 __uint64_t u64;
10 } epoll_data_t;
可见 epoll_data 是一个 union 结构体 , 借助于它应用程序可以保存很多类型的信息 :fd 、指针等等。有了它,应用程序就可以直接定位目标了。
select模型的内核必须遍历所有监视的描述符,而应用程序也必须遍历所有描述符,检查哪些描述符已经准备好。当描述符成百上千时,会变得非常低效——这是select(poll)模型低效的根源所在。考虑这些情况,2.6以后的内核都引进了epoll模型。