进程与进程树当一个程序在系统中运行时,会产生一个进程。什么创建了程序进程?可以理解为系统的调度进程,创建程序进程。那么,是谁创建了系统调度进程呢?在系统中,新进程只能从父进程(fork)产生。pid为0的进程是内核创建的init进程(祖先进程)。pid为0的进程不能被杀死。进程pidpid是进程号。系统中的每个进程都有一个唯一的编号,而且编号是有限的。如果进程号用完,则不能创建新进程。进程树根据上面的描述,进程肯定是由父进程fork()产生的,所以进程的结构可以通过树结构来描述。如:cmd->notepad.exe那么:cmd就是notepad.exe的父进程。在任务管理器中,有一个函数叫结束进程树,意思是结束进程,同时结束该进程创建的所有子进程。当进程树为cmd结束时,notepad.exe的进程也会被终止孤儿进程、僵尸进程zombieprocess僵尸进程:一个进程使用fork创建子进程,如果子进程退出,父进程不退出不调用wait或waitpid获取子进程的状态信息,则子进程的进程描述符(pid)仍然保存在系统中,无法释放重用。这样的进程称为僵尸进程。在Linux中执行ps命令,可以看到进程列表和进程的状态。正常状态:R(运行状态)、S(睡眠状态)、D(磁盘休眠状态)、T(停止状态)、X(死亡状态)僵尸状态:Z(僵尸进程)僵尸进程无法用kill命令杀死,因为kill命令只是用来终止进程的,僵尸进程已经被终止了。僵尸进程会一直占用pid资源。太多的僵尸进程会导致系统没有可用的pid,从而无法创建新的进程,危害极大。任何一个子进程终止后,都不会立即消失,而是留下一个僵尸,称为进程(Zombie)的数据结构,等待父进程处理。这是每个子进程最后要经历的阶段。如果子进程终止后父进程没有及时处理,可以使用ps命令查看子进程的状态为“Z”。如果父进程能够及时处理,可能来不及用ps命令看到子进程的僵尸状态,但这并不代表子进程不渡过僵尸状态。如果父进程在子进程结束前退出,子进程就会被init进程接管,成为孤儿进程。wait()/waitpid()父进程清理子进程,如下所述。一旦PID进程被释放,一旦调用wait就会立即阻塞自己。Wait自动分析当前进程的子进程是否已经退出。如果发现一个子进程已经变成僵尸,wait就会收集这个子进程的信息,彻底销毁并返回;如果没有找到这样的A子进程,就会阻塞在这里等待,直到出现一个。waitpid()的功能比wait()多,大家可以搜索一下wait()会不会在需要的时候一直阻塞?那么父进程不是不能处理其他工作吗?父进程可以阻塞等待子进程结束,也可以非阻塞查询是否有子进程等待清理(即轮询方式)。使用第一种方法,父进程在阻塞时无法处理自己的工作;第二种方法,父进程在处理自己的工作时,必须要记得时不时地进行轮询,程序实现比较复杂。实际上,当子进程终止时,它会向父进程发送SIGCHLD信号。该信号默认的处理动作是忽略。父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需要专注于自己的工作,不需要关心子进程。是的,子进程终止时会通知父进程,父进程可以在信号处理函数中调用wait清理子进程。上述开发过程(fork、wait)都是底层的基础功能。其他高级语言,比如Java、Python等,在开发进程的时候,都封装了API供我们调用,所以不用担心僵尸进程的产生。孤儿进程一个父进程退出,而它的一个或多个子进程仍在运行,那么那些子进程就会成为孤儿进程。孤儿进程会被init进程(祖先进程)收养并由init进程管理,所以孤儿进程不会成为僵尸进程。也没有坏处。init进程会循环wait()子进程,保证没有子进程成为僵尸进程,所以孤儿进程被init进程收养,这还是一个web服务器非常安全的概念。Web服务器通过监听端口和HTTP协议与客户端通信。终端通讯。通常,Web服务器监听80端口,接收来自浏览器等客户端的HTTP请求,并反馈响应信息。Web服务器有很多种,适用于不同的应用场景。常见的Web服务器包括:Apache、Nginx、Tomcat等。Apache、Nginx比Apache有优势。Apache的rewrite比nginx强,rewrite(rewrite/forward/redirect)频繁在使用apache的情况下,支持各种规则来配置apache。到现在,模块多到基本上能想到的都能找到,所以可以多做apache比较成熟,bug比较少,nginxbug比较多apache比较稳定。Apache有很多模块,对PHP的支持相对容易。Nginx比较麻烦。Apache在处理动态请求方面有优势(模块多,可以通过加载不同的模块来处理各种语言的动态请求),nginx在这方面没用,本身不支持动态请求处理,需要更多的组件和配置来支持。Nginx的优点是轻量级,同时也作为一个web服务,比Apache占用更少的内存和资源;抗并发,高吞吐,nginx处理请求是异步非阻塞的,而Apache是??阻塞的,在高并发下nginx可以保持低资源消耗和高性能;高度模块化设计,编写模块相对简单;社区活跃,各种高性能模块快速发布。综上所述,Nginx的静态处理性能是Apache的3倍以上。Apache对PHP的支持比较简单。Nginx需要配合其他后端组件(PHP-FPM),配置比较麻烦。所以现在对于一些大型的系统,通常都是使用nginx作为转发服务,由多个apaches处理动态请求,然后返回给nginx。即负载均衡,多apache+php水平扩展,可以提高系统吞吐量和并发度。如果是单台服务器,建议使用Nginx+PHP+PHP-FPM(后文介绍)为什么Nginx的吞吐量高?因为Nginx处理请求是异步和非阻塞的,而Apache是同步阻塞的。所以Nginx吞吐量高但相对不稳定,而Apache相对稳定但吞吐量相对较低。阻塞程序执行时,遇到耗时操作(IO),等待耗时执行完成再继续向下执行就是阻塞。非阻塞程序在执行时,遇到耗时操作(IO)时,后续代码可以继续执行,无需等待其完成。非阻塞同步程序在执行时,遇到耗时操作(IO)时,等待耗时操作的反馈结果,进一步向下执行是同步的。异步程序(主线程)在执行时,遇到一个耗时操作(IO),启动一个新的线程,处理这个耗时操作,主线程继续执行代码,做自己的事情,并然后在耗时操作获取结果时通知主线程获取结果;它是异步的。异步最常见的实现是:消息模型;(线程间通信)Apache工作模式1.beos工作模式beos工作模式(与linux无关,或暂时不可用)Beos系统上的工作模式,使用单独的控制线程来创建和控制处理请求的工作线程。2.事件工作模式(不是很稳定,或者暂时不能用)。由于事件模式将服务进程与连接分离,所以在启用KeepAlive的情况下,它可以承受比worker模式更高的负载。事件模式是worker开发的变体模式,配置和使用说明与worker完全一致。但是event模式对https访问的支持不是很好,有时候会出现一系列的问题。3.worker模式(对php不好用,或者暂时不能用)。worker模式使用线程来处理请求,因此可以处理海量请求,系统资源的开销比基于进程的服务器要少。同时worker模式也使用了多进程,每个进程有多个线程来获得基于进程的服务器的稳定性。4、mpmt_os2工作模式(很少使用,或者暂时不用)mpmt_os2是一个针对OS/2优化的混合多进程多线程多处理模块(MPM)。5、Linux的Prefork工作模式:(本文主角,使用最多,最稳定的工作模式)Prefork工作模式是Linux下安装Apache时默认的工作模式,也是最常用的工作模式。为了简单理解其工作原理,下面是一个进程:有一个正在运行的Apache服务器,当用户A访问Apache时,Apache创建一个新的进程1来处理用户A的请求。此时另一个用户B访问apache,apache新建进程2处理用户B的请求。后来用户C、D、E访问apache,apache新建进程3、4、5处理他们的请求。如果每次有新用户访问apache,apache就新建一个进程来处理用户的请求,是不是太慢了?所以apache的prefork模式在apache第一次启动的时候创建了5个进程,等待用户的连接请求,当用户访问的时候,就有一个进程去处理他的请求。那么如果有5个用户同时访问apache,apache第一次创建的5个进程就全部用完了,所以apache会重新重新创建5个进程,等待下一批用户请求。当请求被处理后,进程将被关闭,资源将被释放。prefork模式会根据服务器的硬件情况,设置apache最多只能同时创建256个进程。当并发>=256个进程时,未入队的请求会阻塞等待,等待空闲进程同步处理后,再进入队列处理。(所以apache是??同步阻塞的)Windows下的Apache是??多线程的,不是多进程的!由于Windows下prefork方式创建进程比较耗资源(Win进程方式的缺陷),所以Windows下的Apache是??多线程的而不是多进程的!所以在下载Win版php的时候,会要求选择线程安全版和非线程安全版。这个我们以后再说!Nginx的工作模式是多线程工作模式,不是多进程;nginx收到一个请求后,不会等到请求处理完毕,拿到结果再接收下一个请求,而是异步处理,然后循环(无阻塞)立即接收下一个请求。从处理请求到得到结果的过程是异步的。得到结果后,会主动通知Nginx;这样,每个请求都可以立即接收并处理,而无需等待很长时间。处理完成后,会主动通知回调线程返回数据。这样的工作模式具有超高的吞吐量(所以Nginx是异步非阻塞的)什么是CGi、FastCgi、PHP-FPM?CGi通用网关接口,可以理解为处理动态请求的始祖!最早的时候,互联网只能返回静态页面,后来出现了CGI,后来有人用CGI技术写动态网站;例如:http://guodongxiaren.me/cgi-bin/helloworld.cgiCGi可以使用C/C++、Perl、VB、DELPHI、unix/linuxshell、python等支持标准输入输出流的语言进行开发;Apache有一个模块是支持Cgi的,所以你可以写一个Cgi程序托管到Apache上去体验,具体过程不再赘述,可以自行百度;(Nginx不支持传统的Cgi)Cgi工作模式:客户端http请求消息流=>Apache=>Cgi=>标准输入获取流=>拼接协议输出流=>返回给客户端;也有一些语言为Cgi扩展了库,使其不需要手动拼凑协议,封装了一些常用的功能;但是CGI还没有流行起来;因为每次HTTP请求CGI时,Web服务器都会启动一个新的进程来执行这个CGI程序,即具有Unix特性的fork-and-execute。当有大量用户请求时,这种fork-and-execute操作会严重降低web服务器的性能。时势造英雄,FastCGI(简称FCGI)技术应运而生。简单来说,它的本质就是一种驻留在内存中的进程池技术。调度器负责将传递过来的请求发送给进程池中的进程。一个请求处理完后,处理进程不会被销毁,继续等待下一个请求。请求来了。FastCgi以PHP的PHP-FPM为例:如上图:Apache和Nginx都支持FastCgi的工作方式,只是它们的配置方式不同。当请求到达Apache/Nginx时,Apache/Nginx会将请求转发给FastCgiFastCgi调度进程Pool,分析请求并处理请求,返回给Apache/NginxApache/Nginx反馈结果给客户端需要了解:FastCgi是一个独立程序,它监听端口,等待请求;所以可以和Apache/Nginx部署在同一台服务器的一台机器上,也可以分开分布式部署;Nginx/Apache有点像客户端,将从浏览器获取的请求流通过Tcp/ip技术发送给FastCgi,所以不管FastCgi部署在哪台机器上,只要他们的网络通常都能正常工作。Nginx/Apache和FastCgi也支持UnixSocket(与宿主进程间通信),但是Nginx/Apache和FastCgi必须在同一台机器上;其实FastCgi并不是一个产品,而是一个标准,很多常见的FastCgi产品有:PHP-FPM、支持PHP解析的FastCgispawn-fcgi、支持Python解析的FastCgi(只要支持FastCgi标准的都可以)与Nginx/Apache结合使用;根据不同的实现,可以解析不同语言的服务器端代码,完成请求的动态处理)PHP-FPM#Nginx配置FastCgi,在请求网站下的.php文件时,反向代理将其转发到php-fpmlocation~\.php${roothtml/wordpress;fastcgi_pass127.0.0.1:9000;fastcgi_index索引.php;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;包括fastcgi_params;#fastcgi_cachefastcgi_cache_zone;#指定缓存区的名称#fastcgi_cache_key$host$request_uri;#定义缓存的key,根据缓存文件名的md5值#fastcgi_gicache_validc10mast_validca2003023023011d;#fastcgi_cache_valid任何1m;}##---------------------------------------------------#Apache配置FastCgi#1.配置httpd.conf,加载支持cgi请求转发的模块LoadModuleproxy\_modulemodules/mod\_proxy.soLoadModuleproxy\_fcgi\_modulemodules/mod\_proxy\_fcgi.so#2。转发.php到php-fProxyPassMatch^/(.*\.php(/.*)?)$fcgi://php-fpm:9000/v/php-fpm/www/$1from:https://www.jianshu.com/p/93e2cbdfd209;更多信息,百度上面对FastCGi的概念进行了解释,现在详细说说PHP5.3之后,内置的FastCgi实现,PHP-FPM;php-fpm是一个进程管理器,php-fpm实现了fastcgi协议来管理php-cgi;php-cgi是解释php程序的,它是一个PHP解析器;php-fpm会先启动一个master进程,解析配置文件(php.ini),初始化执行环境,然后启动多个worker。当一个请求来的时候,master会交给一个worker来处理这个请求,然后worker进程不关闭,等待下一个请求php-fpm可以不用重启就可以更改配置,但是更新配置顺利的原因是这样的:php.ini的配置更改后,工作的worker进程仍然使用旧的配置(下次工作时,会使用新配置);当有新的请求过来,交给一个worker进程的时候,新的配置也会同时交给worker。工作进程在工作时,使用新的配置来解析和执行PHP代码;PHP-FPM现在已经很成熟了,支持Nginx+PHP-FPM也支持Apache+PHP-FPMNginx+PHP还是Apache+PHP?Nginx+PHP+PHP-FPM成为了当前流行的搭配环境。Nginx具有高吞吐量。PHP-FPM非常成熟。PHP-FPM可分布式部署,TCP/Unixsocket通信,支持横向扩展较好;A:Apache+PHP:LoadModuleMode使用PHP作为Apache的Module,可以轻松快速搭建PHP环境,以及将PHP配置为.so(.dll)动态库给Apache成为Apache的扩展,相当于Apache具备解析PHP的能力,但是这种方式有相应的缺陷;1.Apache和PHP集成。如果修改了PHP的配置,需要重启Apache来支持新的配置。2、前面说了,Apache是??在Windows下运行的。方法是当一个请求来的时候,开始线程处理,而不是process,所以选择线程安全版本的PHP,但是线程安全,PHP代码的执行和解析效率会更差!【Apache处理多个php请求,在Win下开发多线程,每个线程调用Apache的PHP扩展(动态链接库),解析PHP脚本,返回结果。如果PHP扩展不是线程安全的,会造成线程安全问题,所以在Win下,使用LoadModule的组合模式,选择线程安全版本]B:Apache+PHP-FPM:FastCgi模式下的Apache也支持转发php向PHP-FPM请求,配置方式与Nginx不同;来自:https://www.jianshu.com/p/93e...;更多请查百度;FastCgi模式使用进程来解析请求,所以不存在线程安全问题,无论是在Windows还是Linux上x下可以使用非线程安全版PHPWin环境配置(手动)Nginx+PHPApache+PHP资源下载Apache:Win版Apache,官网不提供二进制下载,需要下载源码并自己编译;但是有一些第三方网站提供了ApacheWindowsBin的下载;(推荐)https://www.apachelounge.com/https://www.apachehaus.com/cg...httpd-2.4.41-win64-VC15.zip2.4.4164位版本的Apache编译用VC15。如果要正常运行,请安装VC15运行库,否则可能会出现问题!您可以在官网以下位置下载对应的运行时库;Win下的问题:threadsafety还是Notthreadsafe?《Nginx + PHP Or Apache + PHP : Apache + PHP : Load Module模式》上面已经说明了这个问题。Win+Apache+PHP+LoadModule工作模式:线程安全Win+Apache+PHP+PHP-FPM工作模式:非线程安全Win+Nginx+PHP+PHP-FPM工作模式:Linux下非线程安全,Apache+PHP和Apache+PHP-FPM都是以多进程的形式工作,不用担心线程安全!Linux环境配置(手动)Nginx+PHPApache+PHP源码安装、二进制安装包安装(packagemanager)、集成开发环境安装集成环境(优点:方便;缺点:Apache、Mysql、PHP版本不能选择,不进行功能定制,所有模块和功能基本都安装好了)源码手动安装(生产服务器会用到),这种方法类似于定制衣服,会更合身。在现场编译的方式下,编译器会根据当前的服务器硬件和服务器系统环境进行相关的编译优化。编译环境更适合现在的硬件,运行速度会更好。(优点:效率高,可定制,可选择模块;缺点:配置麻烦)rpm包(二进制安装包)可以通过yum、apt、brew轻松管理包和包依赖(优点:可定制版本,但是不能自定义功能;)源码包的安装比较费时间,3天左右,因为Apache是??模块化的,编译的时候需要根据系统选择模块,PHP也是模块化的,需要根据编译系统需要的模块进行编译。那为什么不能加载所有模块呢?第一是加载更多的模块会消耗更多的资源,第二是加载更多的模块会增加安全风险,出现漏洞的风险更大。
