WebServer原理分析及对比-nginx-apache-swoole
看了那么多文章,这里自己整理消化下!具体点可以参考前面你的各个文章
因为是从事PHP的web开发所以本篇 主要以php的webServer展开
在这么多年的工作中关于服务器一直处在初步了解、会搭建配置、但是并没有深入的了解和总结。有很多概念不是很清晰例如:
FastCgi与PHP-fpm什么关系?
php-cgi是什么东东?
apache与Nginx相比为什么apache稳定而nginx性能更高
近期比较热的Swoole为什么能够在性能上面有更出色的表现
同步、异步、并行、串行、进程、线程等等概念到底是怎么影响整个系统的运行模式,不同的策略各自的利弊又是什么
这里对上面的问题进行一些归纳整理
一:进程、线程?
进程是具有一定独立功能的,在计算机里面已经运行的程序实体, 进程是基本的运作单位就像学校的班级、工厂的每一条流水线或者车间一样是独立的,并且正在运行的。在早期的系统中(例如Linux2.4以前)进程是基本的运作单位,而在支持线程的系统中(windows,Linux2.6)中线程才是基本的运作单位,进程只是线程的容器,随着硬件越来越强劲多核、超大内存,多线程能够更好的发挥计算机的性能。多个线程能够在多个cpu同时运行。这里要注意进程跟进程是独立的,而线程跟线程部分数据是共享的。
二:同步、异步、并行、串行
这里的同步、异步、并行、串行不一定非得是进程或者线程其实是一种概念或者理念,但是现在最常用的是在线程面 同步异步主要是在时效纬度。并行和串行主要是在执行的纬度上面
从线程的时效来看,分别同步和异步
同步:就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,程序也不会接着往下执行。按照这个定义,其实绝大多数函数都是同步调用。
异步:当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调(Handler机制)来通知调用者。
从线程的执行来看,线程队列分为串行队列和并行队列
串行队列:串行队列的特点是队列内的线程是一个一个执行,直到结束。
并行队列:并行队列的特点是队列中所有线程的执行结束时必须是一块的,队列中其他线程执行完毕后,会阻塞当前线程等待队列中其他线程执行,然后一块执行完毕。
(1)串行同步
图1是串行同步的情况,队列中的线程依次执行,并且主线程阻塞,等待任务的完成。
(2)串行异步
图2是串行异步的情况,队列中的线程依次执行,同时主线程还在继续执行。
(3)并行同步
图3是并行同步的情况,队列中的线程,会一起执行,但是同一时段只能有一个线程执行其他线程等待,等所有任务执行完,主线程继续执行。
(4)并行异步
图4是并行异步的情况,队列中的线程,一起执行,主线程也会继续执行。
由上图可以发现,串行和并行最大的不同的就是执行上,串行是依次执行,只有当前线程结束之后,另一个线程才开启。而并行是所有任务一起执行,执行的表现形式不同。
三:阻塞、非阻塞
阻塞和非阻塞指的是执行一个操作是等操作结束再返回,还是马上返回。
这个跟同步异步有可能搞混,同步的都是阻塞的,但是异步的可以是阻塞或者是非阻塞的。
四:I/O五种模型
I/O其实就是对外设(磁盘,内存,数据库等)的访问,分为请求和执行两个阶段。执行才是真正的I/O,在Linux2.6以前只有请求是异步事件,2.6以后才引入了AIO,执行异步化,根据阻塞、非阻塞,异步非异步可以把I/O分为五种
再来说下各种I/O模型
阻塞I/O:所有过程全阻塞
非阻塞I/O:如果没有数据buffer,则立即返回EWOULDBLOCK
I/O复用(select和poll):在wait和copy阶段分别阻塞
信号驱动I/O(SIGIO):在wait阶段不阻塞,但copy阶段阻塞(信号驱动I/O,即通知)
异步I/O(aio):完全无阻塞方式,当I/O完成是提供信号
越往后、阻塞越少,理论上效率也是最优。五种I/O模型中,前三种属于同步,后两种属于异步。
了解了上面的基本概念(如果要深入了解肯定需要进一步的查阅相关资料)我们具体的分析下webserver
五、常见Web服务方式
Web服务器要为用户提供服务,必须以某种方式,工作在某个套接字上。一般Web服务器在处理用户请求是,一般有如下三种方式可选择:多进程方式、多线程方式、异步方式。
多进程方式:为每个请求启动一个进程来处理。由于在操作系统中,生成进程、销毁进程、进程间切换都很消耗CPU和内存,当负载高是,性能会明显降低。
优点: 稳定性!由于采用独立进程处理独立请求,而进程之间是独立的,单个进程问题不会影响其他进程,因此稳定性最好。
缺点: 资源占用!当请求过大时,需要大量的进程处理请求,进程生成、切换开销很大,而且进程间资源是独立的,造成内存重复利用。
多线程方式:一个进程中用多个线程处理用户请求。由于线程开销明显小于进程,而且部分资源还可以共享,因此效率较高。
优点:开销较小!线程间部分数据是共享的,且线程生成与线程间的切换所需资源开销比进程间切换小得多。
缺点:稳定性!线程切换过快可能造成线程抖动,且线程过多会造成服务器不稳定。
异步方式:使用非阻塞方式处理请求,是三种方式中开销最小的。但异步方式虽然效率高,但要求也高,因为多任务之间的调度如果出现问题,就可能出现整体故障,因此使用异步工作的,一般是一些功能相对简单,但却符合服务器任务调度、且代码中没有影响调度的错误代码存在的程序。
优点:性能最好!一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。
缺点:稳定性!某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机。
六:如何提高Web服务器的并发连接处理能力
基于线程,即一个进程生成多个线程,每个线程响应用户的每个请求。
基于事件的模型,一个进程处理多个请求,并且通过epoll机制来通知用户请求完成。
基于磁盘的AIO(异步I/O)
支持mmap内存映射,mmap传统的web服务器,进行页面输入时,都是将磁盘的页面先输入到内核缓存中,再由内核缓存中复制一份到web服务 器上,mmap机制就是让内核缓存与磁盘进行映射,web服务器,直接复制页面内容即可。不需要先把磁盘的上的页面先输入到内核缓存去。
六:cgi、php-cgi、fast-cgi、php-fpm
CGI是一种协议,规定从webserver传给具体的解析器的协议,规定了要传那些数据、以什么样的格式传输数据。跟进程没关系。为了保证web-server传递过来的数据是标准格式的,方便具体CGI程序的开发编写。
php-cgi 就是一种cgi协议php形式实现的程序,用来解析从webserver接收到的php请求,并以cgi的形式返回
fast-cgi是什么呢?其实看字面意思就知道是为了提高cgi的性能的,要注意fast-cgi也是一种协议,应该是对cgi的一种增强。每一次cgi请求php解析器都会加载解析php.ini文件,初始化执行环境。每一个标准的cgi都会执行这个步骤。fast-cgi会首先启动一个master把这些通用的标准工作都做完,然后启动多个worker,当请求过来的时候master会把一个请求交给一个worker,然后接收下一个请求。当然还有一些其他的优化来管理cgi进程
php-fpm 前面说了 cgi是一种协议,那么解析php的cgi协议叫php-cgi,fast-cgi是用来一种提高cgi的一种协议,而php-fpm就是一种具体的实现用来管理php-cgi的程序。
这里补充下apache 的模式
apache通过mod_php把php解析器加载进来(php.ini 环境初始化等等),每一次请求都会重复执行这个操作,不管是不是动态请求,css,js,image请求也会执行这个操作,所以会很消耗资源。
六:结合具体实例小结下
网上针对apache、nginx、swoole的具体模块具体性能分析很多,具体实现这里就不一一列举了,其实最核心的就是上面1-5的各种运用,这里不得不再次告诫自己基础的重要性。
apache 目前有三种模式prefork、worker、event。event在最新的版本里面已经稳定可用,但是现在市面上主流的用apache还是采用前两种模式,毕竟如果用apache主要是考虑稳定性,如果用event不如直接用nginx。prefork采用进程模式,worker采用多进程多线程模式。稳定可靠。一般站点apache还是推荐的方案。
nginx 刚才在第五部分说过如何提高web服务器的并发支持能力,nginx支持所有的特性。nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在nginx中,连接请求由为数不多的 几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。但是可能会在稳定性上面不如apache,所以出现了lnamp架构,nginx做分发,apache处理具体的动态脚本。
swoole
swoole官方的说法是PHP异步的网络通信引擎,基于事件驱动(异步IO)编程模式,纯C编写异步多线程。在外设(硬盘,数据库,通信)各个方面都做了异步化处理或者各种优化。在这些基础之上把PHP的脚本常驻内存,这个比nginx更进一步。专门为php的server服务化量身定做的做的一套引擎,所以性能高是有他的道理的,目前很多替代了php-fpm 采用nginx swoole的方案也是不错的选择