作者:酒窝
链接:https://www.zhihu.com/question/23786410/answer/153455460
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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个进程。再多的请求就只能等待前面的进程处理完毕在进行处理。

假设完毕!

上面的假设就是prefork模式的工作原理。但是上面假设中具体的数字不是定死的,而是通过prefork模式的配置来设置的。下面是http.conf中的配置信息。

*带井号的为注释部分

prefork模式的几个重要的参数:

---------------------------------------------------------------------------------------------------------------

名称 默认值 说明

StartServers 5 apache启动时候默认开始的进程数

MinSpareServers 5 最小的闲置进程数

MaxSpareServers 10 最大的闲置进程数

ServerLimit 256 最大的进程总数(参考,实际看MaxClients)

MaxClients 256 最大的进程总数

MaxRequestsPerChild 4000 每个进程处理的最多请求数

----------------------------------------------------------------------------------------------------------------

(1)StartServers:这个看了就明白了。

(2)MinSpareServers:举个例子就明白了。

apache在没有用户访问时候有5个闲置的进程,如果有一个用户访问网站。则闲置的进程就只有4个,这个值小于MinSpareServers,所以apache就以第一秒1个进程,第二秒2个进程,第三秒4个进程的速度新建空闲进程。直到大于等于MinSpareServers个空闲进程才结束。

(3)MaxSpareServers:还是举个例子就明白了。

apache在没有用户访问时候有5个闲置的进程,如果有5个用户同时访问网站。则闲置的进程就只有0个,这个值小于 MinSpareServers,所以apache就以第一秒1个进程,第二秒2个进程,第三秒4个进程的速度新建空闲进程。直到大于等于 MinSpareServers个空闲进程才结束。在这个例子中直到第三秒,一共生成1+2+4个进程才能满足大于等于MinSpareServers的要求。后来这5个用户访问完apache,访问结束,关闭浏览器。所以apache就有了5+7个空闲的进程。这时空闲的进程比较多,apache就开始关闭一些进程,直到满足小于MaxSpareServers个空闲进程才结束。如果该值小于MinSpareServers则apache默认将该值设置成MinSpareServers+1。

(4)ServerLimit:这个参数是控制apache的进程总数的,那为什么会有两个参数控制apache的进程总数呢?这个参数在apache1的时代是没有的,因为那个时候有个256M内存的服务器就很厉害了。后来apache2的时代到来,服务器的硬件也得到升级。很多服务器都是4G内存,还有很多比4G内存大的服务器出现。apache1的时代只有一个MaxClients参数控制进程总数就够了,而这个参数最大值是256定死了。但是到了apache2的时代必须调整ServerLimit值大于256才能使MaxClient支持大于256的值。

(5)MaxClients:apache最大的进程数。apache1的时代只有一个MaxClients参数控制进程总数就够了,而这个参数最大值是256定死了。但是到了apache2的时代必须调整ServerLimit值大于256才能使MaxClient支持大于256的值。

(6)MaxRequestsPerChild:举个例子就明白了。

apache在没有用户访问的时候有5个空闲进程。当一个用户访问网站,访问完又离开。则apache的第一个进程就处理了一个请求,从新进入闲置状态。再有一个用户访问网站,访问完后离开。则apache的第一个进程就处理了1+1个请求。这样继续访问3998个用户,这个进程就处理了4000个请求,之后就自动关闭这个进程。这个时候apache就只有4个限制的进程,小于MinSpareServers值所以apache从今建立一个空闲进程。至于为什么处理完4000个请求就要关闭这个进程呢?答案之一:为了防止内存的泄露。

下面图文介绍这些参数(要深刻理解一个知识就要亲自去体验)

测试环境参数
说明

操作系统
centos4.5(虚拟机)

服务器
apache2.2.6

内存
1G

服务器地址
192.168.212.128

客户端地址
192.168.212.1

测试文件index.php

<?php
for($i = 0;$i <= 10;$i++){
echo date('H:i:s',time());
echo '<br/>';
sleep(10);
}
?>

测试http.conf的prefork模式设置:(设置有点极端,但是可以很好的理解说明)

首先查看apache第一次启动时候的空闲进程:

linux(centos)下查看apache的进程可以使用#ps -ef|grep httpd命令,查看apache进程的内存使用情况可以使用#ps –U apache –u apache u命令

#service httpd restrat:重启apache,初始化进程

#ps -ef|grep httpd:用户名为apache的才是apache用于处理用户请求的进程

#ps –U apache –u apache u:查看用户名为apache的进程(即apache为了处理用户请求而建立的进程详情)

当前为没有任何用户访问时候apache建立StartServers=1个进程

(1)当有一个用户访问(通过本机上的ie浏览器访问虚拟主机上apache服务器模式该情景)

可以看到apache的进程增加为2个,为什么呢?当唯一的空闲进程时候完之后,空闲进程小于MinSpareServers,apache就从新建立一个进程。注意查看RSS值(该进程的内存使用量KB)为4424的空闲进程。

再看看访问完成之后的apache进程数。

可以看到还是只有两个进程,而且这两个进程都是空闲的。

(2)当有两个用户访问(通过本机上的两个ie浏览访问虚拟主机上的apache服务器模拟该情景)

可以看到有两个用户访问的时候apache的进程数增加为3个。为什么呢?当本来空闲2个进程时候完之后,空闲进程小于MinSpareServers,apache就从新建立一个进程。注意查看RSS值(该进程的内存使用量KB)为4424的空闲进程。

再看看访问完成之后的apache进程数。

可以看到空闲的进程数又减少为2个。为什么呢?当两个用户访问完成之后两个用户的进程都会关闭,这时候就会有3个空闲进程,这个值大于MaxSpareServers=2的值。所以apache会自动关掉一个进程满足MaxSpareServers=2的值。

(3)当有三个用户同时访问(通过本机上的三个ie浏览访问虚拟主机上的apache服务器模拟该情景)

可以看到apache的进程有3个,而这三个进程都在处理用户的请求,没有多余的空闲进程产生。为什么呢?因为在上面我们设置了MaxClients的值为3。所以apache最多只会生成3个进程。

再看看这三个用户访问完成之后的apache进程数。

可以看到空闲的进程数又减少为2个。为什么呢?当三个用户访问完成之后三个用户的进程都会关闭,这时候就会有3个空闲进程,这个值大于MaxSpareServers=2的值。所以apache会自动关掉一个进程满足MaxSpareServers=2的值。

(4)当有四个用户同时访问(通过本机上的四个ie浏览访问虚拟主机上的apache服务器模拟该情景)

可以看到虽然有四个用户同时访问,但是apache创建的进程数还是只有3个。就是说apache只对前面的3个用户请求进行了处理。第4个用户只能等待。

这个时候查看apache的TCP连接情况。(对于TCP连接不太理解的可以点击查看

可以看到这4个用户都已经建立了连接。但是apache只处理了前面的3个请求。处理完3个请求在处理最后一个请求,这点可能从文件的打印内容看到。四个用户几乎是同时访问的。

可以看到最后一个用户的请求时间是前面三个用户访问完成之后开始的。

依次类推,当有7个用户同时访问时候又是什么样的?只贴几张图,看了就明白了。

结论

如果从头到尾详细读过本篇文章,会得出如下的结论:

1,apache是严格按照prefork模式的配置参数来进程分配和管理的。不像网上有些文章那样修改了某个值,apache不起作用。只能说您改的不对,或者说您对上面的内容还不够理解。

2,MaxClients值就是apache的最大进程数。不像网上有些文章说的这个值越大越好(有的文章既然推荐该值为4000),您可以从上面的进程图中看到apache的每个进程的%MEM(内存占用百分比)值为0.5%左右。所以这个值的具体设置的最大数位:100/0.5 = 200。而这也只是在这个服务器只有一个apache的情况下。如果服务器有其他程序需要占用内存(比如mysql)这个值要小于200。你总不能把操作系统的所有内存都给apache吧?

3,每个浏览器是一个用户,每个用户就是一条进程。明白意思了吧?我的这台服务器的并发量只有200。就是说我的这台服务器只能支持同时200个用户访问,再多的用户访问就只能是等待。或者说我这台服务器只支持200个浏览器的访问。关于服务器的并发我会在下面一片文章中详细讲解。

4,200的并发量很小吗?要知道apache处理数据的速度是相当快的。一条正常的首页访问可能就一秒钟处理完毕。所以在假想的状态下,我的这台服务器,每分钟可以访问60*200=12000个用户。每天可以访问12000*60*24=17280000个用户的访问。这当然是在完全饱和的访问状态的假想数据。下一篇文章我会详细讲解网站并发,请求,连击等内容。

5,如果访问的用户数大于MaxClients的数,多出的用户不会立刻断掉连接,还是会建立TCP连接。只不过会等待前面的用户处理完在得到相应。在php.ini,http.conf,操作系统设定的超时时间内得不到相应才会断掉连接。

并发的HTTP请求,apache是如何响应的,以及如何调用php文件的的更多相关文章

  1. HTTP请求报文和HTTP响应报文

    HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. HTTP请求报文 一个HTTP请求报文由请求行(request ...

  2. HTTP请求报文和HTTP响应报文(转)

    原文地址:http://blog.csdn.net/zhangliang_571/article/details/23508953 HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串, ...

  3. Apache开启expires响应头,优化缓存

    apache开始expires响应头输出 expires是什么 指示资源什么时候过期的时间值(GMT时间),在指定的过期时间前,浏览器可以直接使用自身缓存的版本,而不用向服务器发请求,大大减轻服务器压 ...

  4. http请求报文格式和响应报文格式

    转载 出处 超文本传输协议(Hypertext Transfer Protocol,简称HTTP)是应用层协议.HTTP 是一种请求/响应式的协议,即一个客户端与服务器建立连接后,向服务器发送一个请求 ...

  5. python通过get,post方式发送http请求和接收http响应的方法,pythonget

    python通过get,post方式发送http请求和接收http响应的方法,pythonget 本文实例讲述了python通过get,post方式发送http请求和接收http响应的方法.分享给大家 ...

  6. python通过get方式,post方式发送http请求和接收http响应-urllib urllib2

    python通过get方式,post方式发送http请求和接收http响应-- import urllib模块,urllib2模块, httplib模块 http://blog.163.com/xyc ...

  7. HTTP请求格式和HTTP响应格式

    主要内容: 1.HTTP请求格式 2.HTTP响应格式 一.HTTP请求格式 当浏览器向Web服务器发出请求时,它向服务器传递了一个数据块,也就是请求信息,HTTP请求信息由3部分组成:l   请求方 ...

  8. (转)HTTP请求报文和HTTP响应报文

    原地址:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/28/2612910.html HTTP报文是面向文本的,报文中的每一个字段都是一些ASC ...

  9. 发出HTTP请求并获得HTTP响应

    发出HTTP请求并获得HTTP响应的过程如下: (1)定义HTTP请求HttpPut(HttpPost/HttpGet/HttpDelete)等: (2)定义各种Header,并加入HttpPut中: ...

  10. Django(十一)请求生命周期之响应内容(请求/响应 头/体)

    https://www.cnblogs.com/renpingsheng/p/7534897.html Django请求生命周期之响应内容 http提交数据的方式有"post",& ...

随机推荐

  1. python记录_day18 反射 判断函数与方法

    一.三个内置函数 1.issubclass(a, b)  判断a类是否是b类的子类 class Foo: pass class Zi(Foo): pass class Sun(Zi): pass pr ...

  2. 漏洞复现——apache文件解析漏洞

    漏洞描述: 我们可以上传一个文件名末尾包含换行符的文件,以此绕过它的黑名单 影响版本: apache 2.4.0-2.4.29 漏洞分析: <FilesMath "\.(?i:php| ...

  3. python中lambda的用法

    一.lambda函数也叫匿名函数,即,函数没有具体的名称.先来看一个最简单例子: def f(x):return x**2print f(4) Python中使用lambda的话,写成这样 g = l ...

  4. C++的面试题

    1.什么是类? 类是具有相同属性和相同的方法的对象的集合,它是一种既包含数据又包含函数的抽象数据类型. 对象是类进行实体化后的产物,是一个实体. 在C++中也是先声明一个类类型,用类去定义若干个同类型 ...

  5. HDU-4587-tarjin/割点

    http://acm.hdu.edu.cn/showproblem.php?pid=4587 给出一幅无向图,问除去两个点之后子图的最大联通分量个数. 考虑每次ban一个点然后跑一遍tarjin统计下 ...

  6. Thirft框架介绍

    1.前言 Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目.Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和 ...

  7. 19. Remove Nth Node From End of List C++删除链表的倒数第N个节点

    https://leetcode.com/problems/remove-nth-node-from-end-of-list/ 使用双指针法,可以仅遍历一次完成节点的定位 /** * Definiti ...

  8. Spring JdbcTemplate 查询结果集Map反向生成Java实体(转)

    原文地址:Spring JdbcTemplate 查询结果集Map反向生成Java实体 以前写过一篇文章吐槽过Spring JdbcTemplate的queryForList方法(参见:http:// ...

  9. PHPCMS V9完全开发介绍

    PHPCMS V9 文件目录结构: 根目录 | – api 接口文件目录 | – caches 缓存文件目录 | – configs 系统配置文件目录 | – caches_* 系统缓存目录 | – ...

  10. 什么是 开发环境、测试环境、生产环境、UAT环境、仿真环境

    开发环境:开发环境是程序猿们专门用于开发的服务器,配置可以比较随意, 为了开发调试方便,一般打开全部错误报告. 测试环境:一般是克隆一份生产环境的配置,一个程序在测试环境工作不正常,那么肯定不能把它发 ...