<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[Ops运维 | Mr`kang Blog｜小豆子]]></title> 
<link>https://www.cnmysql.com/index.php</link> 
<description><![CDATA[关注服务器运维技术、DB优化、Docker虚拟化、自动化运维、工作积累]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[Ops运维 | Mr`kang Blog｜小豆子]]></copyright>
<item>
<link>https://www.cnmysql.com/post//</link>
<title><![CDATA[对apache中并发控制参数prefork理解和调优]]></title> 
<author>kangyang &lt;kangyang315@qq.com&gt;</author>
<category><![CDATA[WEB技术]]></category>
<pubDate>Wed, 23 Jul 2014 07:11:31 +0000</pubDate> 
<guid>https://www.cnmysql.com/post//</guid> 
<description>
<![CDATA[ 
	<span style="font-size: 12px;"><span style="font-family: 宋体;">一个apache有linux下的并发不是很高的,大约到3K的样子(其实处理的http的请求可能只有300/s),普通的服务器都会不同程度的出现问题.apache有关并发控制主要是 prefork和worker二个其中一个来控制.我们可以使用httpd -l来确定当前使用的MPM是prefork.c,还是Worker.c.下面是apache中有关prefork的配置.下面是我优化过的参数.<br/><br/>1. <IfModule prefork.c> <br/>2. <br/>3. #有这个参数就不必像apache1一样修改源码才能修改256客户数的限制,听讲要放到最前面才会生效,2000是这个参数的最大值 <br/>4. ServerLimit 2000 <br/>5. #指定服务器启动时建立的子进程数量，prefork默认为5。 <br/>6. StartServers 25 <br/>7. <br/>8. #指定空闲子进程的最小数量，默认为5。如果当前空闲子进程数少于MinSpareServers ，那么Apache将以最大每秒一个的速度产生新的子进程。此参数不要设的太大。 <br/>9. MinSpareServers 25 <br/>10. <br/>11. #设置空闲子进程的最大数量，默认为10。如果当前有超过MaxSpareServers数量的空闲子进程，那么父进程将杀死多余的子进程。此参数不要设的太大。如果你将该指令的值设置为比MinSpareServers小，Apache将会自动将其修改成”MinSpareServers+1″。 <br/>12. MaxSpareServers 50 <br/>13. <br/>14. #限定同一时间客户端最大接入请求的数量(单个进程并发线程数)，默认为256。任何超过MaxClients限制的请求都将进入等候队列,一旦一个链接被释放，队列中的请求将得到服务。要增大这个值，你必须同时增大ServerLimit 。 <br/>15. MaxClients 2000 <br/>16. <br/>17. #每个子进程在其生存期内允许伺服的最大请求数量，默认为10000.到达MaxRequestsPerChild的限制后，子进程将会结束。如果MaxRequestsPerChild为”0″，子进程将永远不会结束。 <br/>18. MaxRequestsPerChild 10000 <br/>19. <br/>20. </IfModule><br/><br/>将MaxRequestsPerChild设置成非零值有两个好处： <br/>1.可以防止(偶然的)内存泄漏无限进行，从而耗尽内存。 <br/>2.给进程一个有限寿命，从而有助于当服务器负载减轻的时候减少活动进程的数量。<br/><br/>工作方式： <br/>一个单独的控制进程(父进程)负责产生子进程，这些子进程用于监听请求并作出应答。Apache总是试图保持一些备用的 (spare)或者是空闲的子进程用于迎接即将到来的请求。这样客户端就不需要在得到服务前等候子进程的产生。在Unix系统中，父进程通常以root身份运行以便邦定80端口，而 Apache产生的子进程通常以一个低特权的用户运行。User和Group指令用于设置子进程的低特权用户。运行子进程的用户必须要对它所服务的内容有读取的权限，但是对服务内容之外的其他资源必须拥有尽可能少的权限。<br/><br/>对上面的有些值，一定要记的不是越大越好.这个需要经过几次尝试和出错之后才能选好要使用的值(不同的硬件处理水平不一样)。最重要的值是 maxclient允许足够多的工作进程，同时又不会导致服务器进行过度的交换(死机)。如果传入的请求超出处理能力而让服务器当掉的话，那么至少满足此值的那些请求会得到服务，其他请求被阻塞这样会更加好。<br/><br/>我们调优常常要查看httpd进程数（即prefork模式下Apache能够处理的并发请求数）：<br/><br/>1. #ps -ef &#124; grep httpd &#124; wc -l<br/><br/>出现的结果,就是当前Apache能够处理的多少个并发请求，这个值Apache根据负载情况自动调.<br/><br/>查看Apache的并发请求数及其TCP连接状态：<br/><br/>1. #netstat -n &#124; awk ‘/^tcp/ &#123;++S[$NF]&#125; END &#123;for(a in S) print a, S[a]&#125;’<br/><br/>返回结果示例： <br/>LAST_ACK 5 <br/>SYN_RECV 30 <br/>ESTABLISHED 1597 <br/>FIN_WAIT1 51 <br/>FIN_WAIT2 504 <br/>TIME_WAIT 1057 <br/>其中的SYN_RECV表示正在等待处理的请求数；ESTABLISHED表示正常数据传输状态；TIME_WAIT表示处理完毕，等待超时结束的请求数。<br/><br/>状态：描述 <br/>CLOSED：无连接是活动的或正在进行 <br/>LISTEN：服务器在等待进入呼叫 <br/>SYN_RECV：一个连接请求已经到达，等待确认 <br/>SYN_SENT：应用已经开始，打开一个连接 <br/>ESTABLISHED：正常数据传输状态 <br/>FIN_WAIT1：应用说它已经完成 <br/>FIN_WAIT2：另一边已同意释放 <br/>ITMED_WAIT：等待所有分组死掉 <br/>CLOSING：两边同时尝试关闭 <br/>TIME_WAIT：另一边已初始化一个释放 <br/>LAST_ACK：等待所有分组死掉<br/><br/>可以使用Linux下的webbench来作压力测试.<br/><br/>Apache 2.0性能优化-MPM的选择与配置<br/><br/>Apache 2.0在性能上的改善最吸引人。在支持POSIX线程的Unix系统上，Apache可以通过不同的MPM运行在一种多进程与多线程相混合的模式下，增强部分配置的可扩充性能。相比于Apache 1.3，2.0版本做了大量的优化来提升处理能力和可伸缩性，并且大多数改进在默认状态下即可生效。但是在编译和运行时刻，2.0也有许多可以显著提高性能的选择。本文不想叙述那些以功能换取速度的指令，如HostnameLookups等，而只是说明在2.0中影响性能的最核心特性：MPM（Multi -Processing Modules，多道处理模块）的基本工作原理和配置指令。<br/><br/>毫不夸张地说，MPM的引入是Apache 2.0最重要的变化。大家知道，Apache是基于模块化的设计，而Apache 2.0更扩展了模块化设计到Web服务器的最基本功能。服务器装载了一种多道处理模块，负责绑定本机网络端口、接受请求，并调度子进程来处理请求。扩展模块化设计有两个重要好处：<br/><br/>◆ Apache可以更简洁、有效地支持多种操作系统；<br/><br/>◆ 服务器可以按站点的特殊需要进行自定制。<br/><br/>在用户级，MPM看起来和其它Apache模块非常类似。主要区别是在任意时刻只能有一种MPM被装载到服务器中。<br/><br/>指定MPM的方法<br/><br/>下面以Red Hat Linux 9为平台，说明在Apache 2.0中如何指定MPM (Apache采用2.0.45)。先解压缩源代码包httpd-2.0.45.tar.gz，生成httpd-2.0.45目录（Apache 1.3源代码包的命名规则是apache_1.3.NN.tar.gz，而2.0版则是httpd-2.0.NN.tar.gz，其中NN是次版本号）。<br/><br/>进入httpd-2.0.45目录，运行以下代码：<br/><br/>1. $ ./configure –help&#124;grep mpm<br/><br/>显示如下：<br/><br/>1. –with-mpm=MPM <br/>2. Choose the process model for Apache to use. <br/>3. MPM=&#123;beos&#124;worker&#124;prefork&#124;mpmt_os2&#124; perchild&#124;leader&#124;threadpool&#125;<br/><br/>上述操作用来选择要使用的进程模型，即哪种MPM模块。Beos、mpmt_os2分别是BeOS和OS/2上缺省的MPM， perchild主要设计目的是以不同的用户和组的身份来运行不同的子进程。这在运行多个需要CGI的虚拟主机时特别有用，会比1.3版中的SuExec 机制做得更好。leader和threadpool都是基于worker的变体，还处于实验性阶段，某些情况下并不会按照预期设想的那样工作，所以 Apache官方也并不推荐使用。因此，我们主要阐述prefork和worker这两种和性能关系最大的产品级MPM ( 有关其它的MPM详细说明，请参见Apache官方文档：<a href="http://httpd.apache.org/docs-2.0/mod/)" target="_blank">http://httpd.apache.org/docs-2.0/mod/)</a>。<br/><br/>prefork的工作原理及配置<br/><br/>如果不用”–with-mpm”显式指定某种MPM，prefork就是Unix平台上缺省的MPM。它所采用的预派生子进程方式也是 Apache 1.3中采用的模式。prefork本身并没有使用到线程，2.0版使用它是为了与1.3版保持兼容性；另一方面，prefork用单独的子进程来处理不同的请求，进程之间是彼此独立的，这也使其成为最稳定的MPM之一。<br/><br/>若使用prefork，在make编译和make install安装后，使用”httpd -l”来确定当前使用的MPM，应该会看到prefork.c（如果看到worker.c说明使用的是worker MPM，依此类推）。再查看缺省生成的httpd.conf配置文件，里面包含如下配置段：<br/><br/>1. <IfModule prefork.c>; <br/>2. StartServers 5 <br/>3. MinSpareServers 5 <br/>4. MaxSpareServers 10 <br/>5. MaxClients 150 <br/>6. MaxRequestsPerChild 0 <br/>7. </IfModule><br/><br/>prefork的工作原理是，控制进程在最初建立”StartServers”个子进程后，为了满足MinSpareServers设置的需要创建一个进程，等待一秒钟，继续创建两个，再等待一秒钟，继续创建四个……如此按指数级增加创建的进程数，最多达到每秒32个，直到满足 MinSpareServers设置的值为止。这就是预派生（prefork）的由来。这种模式可以不必在请求到来时再产生新的进程，从而减小了系统开销以增加性能。<br/><br/>MaxSpareServers设置了最大的空闲进程数，如果空闲进程数大于这个值，Apache会自动kill掉一些多余进程。这个值不要设得过大，但如果设的值比MinSpareServers小，Apache会自动把其调整为MinSpareServers+1。如果站点负载较大，可考虑同时加大 MinSpareServers和MaxSpareServers。<br/><br/>MaxRequestsPerChild设置的是每个子进程可处理的请求数。每个子进程在处理了”MaxRequestsPerChild” 个请求后将自动销毁。0意味着无限，即子进程永不销毁。虽然缺省设为0可以使每个子进程处理更多的请求，但如果设成非零值也有两点重要的好处：<br/><br/>◆ 可防止意外的内存泄漏；<br/><br/>◆ 在服务器负载下降的时侯会自动减少子进程数。<br/><br/>因此，可根据服务器的负载来调整这个值。笔者认为10000左右比较合适。<br/><br/>MaxClients是这些指令中最为重要的一个，设定的是Apache可以同时处理的请求，是对Apache性能影响最大的参数。其缺省值 150是远远不够的，如果请求总数已达到这个值（可通过ps -ef&#124;grep http&#124;wc -l来确认），那么后面的请求就要排队，直到某个已处理请求完毕。这就是系统资源还剩下很多而HTTP访问却很慢的主要原因。系统管理员可以根据硬件配置和负载情况来动态调整这个值。虽然理论上这个值越大，可以处理的请求就越多，但Apache默认的限制不能大于256。如果把这个值设为大于256，那么 Apache将无法起动。事实上，256对于负载稍重的站点也是不够的。在Apache 1.3中，这是个硬限制。如果要加大这个值，必须在”configure”前手工修改的源代码树下的src/include/httpd.h中查找 256，就会发现”#define HARD_SERVER_LIMIT 256″这行。把256改为要增大的值（如4000），然后重新编译Apache即可。在Apache 2.0中新加入了ServerLimit指令，使得无须重编译Apache就可以加大MaxClients。下面是笔者的prefork配置段：<br/><br/>1. <IfModule prefork.c> <br/>2. StartServers 10 <br/>3. MinSpareServers 10 <br/>4. MaxSpareServers 15 <br/>5. ServerLimit 2000 <br/>6. MaxClients 1000 <br/>7. MaxRequestsPerChild 10000 <br/>8. </IfModule><br/><br/>上述配置中，ServerLimit的最大值是20000，对于大多数站点已经足够。如果一定要再加大这个数值，对位于源代码树下server/mpm/prefork/prefork.c中以下两行做相应修改即可：<br/><br/>1. #define DEFAULT_SERVER_LIMIT 256 <br/>2. #define MAX_SERVER_LIMIT 20000<br/><br/>worker的工作原理及配置<br/><br/>相对于prefork，worker是2.0 版中全新的支持多线程和多进程混合模型的MPM。由于使用线程来处理，所以可以处理相对海量的请求，而系统资源的开销要小于基于进程的服务器。但是， worker也使用了多进程，每个进程又生成多个线程，以获得基于进程服务器的稳定性。这种MPM的工作方式将是Apache 2.0的发展趋势。<br/><br/>在configure -with-mpm=worker后，进行make编译、make install安装。在缺省生成的httpd.conf中有以下配置段：<br/><br/>1. <IfModule worker.c> <br/>2. StartServers 2 <br/>3. MaxClients 150 <br/>4. MinSpareThreads 25 <br/>5. MaxSpareThreads 75 <br/>6. ThreadsPerChild 25 <br/>7. MaxRequestsPerChild 0 <br/>8. </IfModule><br/><br/>worker的工作原理是，由主控制进程生成”StartServers”个子进程，每个子进程中包含固定的ThreadsPerChild 线程数，各个线程独立地处理请求。同样，为了不在请求到来时再生成线程，MinSpareThreads和MaxSpareThreads设置了最少和最多的空闲线程数；而MaxClients设置了所有子进程中的线程总数。如果现有子进程中的线程总数不能满足负载，控制进程将派生新的子进程。<br/><br/>MinSpareThreads和MaxSpareThreads的最大缺省值分别是75和250。这两个参数对Apache的性能影响并不大，可以按照实际情况相应调节。<br/><br/>ThreadsPerChild是worker MPM中与性能相关最密切的指令。ThreadsPerChild的最大缺省值是64，如果负载较大，64也是不够的。这时要显式使用 ThreadLimit指令，它的最大缺省值是20000。上述两个值位于源码树server/mpm/worker/worker.c中的以下两行：<br/><br/>1. #define DEFAULT_THREAD_LIMIT 64 <br/>2. #define MAX_THREAD_LIMIT 20000<br/><br/>这两行对应着ThreadsPerChild和ThreadLimit的限制数。最好在configure之前就把64改成所希望的值。注意，不要把这两个值设得太高，超过系统的处理能力，从而因Apache不起动使系统很不稳定。<br/><br/>Worker模式下所能同时处理的请求总数是由子进程总数乘以ThreadsPerChild值决定的，应该大于等于MaxClients。如果负载很大，现有的子进程数不能满足时，控制进程会派生新的子进程。默认最大的子进程总数是16，加大时也需要显式声明ServerLimit（最大值是 20000）。这两个值位于源码树server/mpm/worker/worker.c中的以下两行：<br/><br/>1. #define DEFAULT_SERVER_LIMIT 16 <br/>2. #define MAX_SERVER_LIMIT 20000<br/><br/>需要注意的是，如果显式声明了ServerLimit，那么它乘以ThreadsPerChild的值必须大于等于MaxClients，而且 MaxClients必须是ThreadsPerChild的整数倍，否则Apache将会自动调节到一个相应值（可能是个非期望值）。下面是笔者的 worker配置段：<br/><br/>1. <IfModule worker.c> <br/>2. StartServers 3 <br/>3. MaxClients 2000 <br/>4. ServerLimit 25 <br/>5. MinSpareThreads 50 <br/>6. MaxSpareThreads 200 <br/>7. ThreadLimit 200 <br/>8. ThreadsPerChild 100 <br/>9. MaxRequestsPerChild 0 <br/>10. </IfModule><br/><br/>通过上面的叙述，可以了解到Apache 2.0中prefork和worker这两个重要MPM的工作原理，并可根据实际情况来配置Apache相关的核心参数，以获得最大的性能和稳定性。<br/><br/>其它更详细的写以到<a href="http://httpd.apache.org/docs-2.0/" target="_blank">http://httpd.apache.org/docs-2.0/</a> <br/>合理设置apache httpd的最大连接数<br/><br/>手头有一个网站在线人数增多，访问时很慢。初步认为是服务器资源不足了，但经反复测试，一旦连接上，不断点击同一个页面上不同的链接，都能迅速打开，这种现象就是说明apache最大连接数已经满了，新的访客只能排队等待有空闲的链接，而如果一旦连接上，在keeyalive 的存活时间内（KeepAliveTimeout，默认5秒）都不用重新打开连接，因此解决的方法就是加大apache的最大连接数。<br/><br/>1.在哪里设置？<br/><br/>服务器的为FreeBSD 6.2 ，apache 2.24，使用默认配置（FreeBSD 默认不加载自定义MPM配置），默认最大连接数是250<br/><br/>在/usr/local/etc/apache22/httpd.conf中加载MPM配置（去掉前面的注释）： <br/># Server-pool management (MPM specific) <br/>Include etc/apache22/extra/httpd-mpm.conf<br/><br/>可见的MPM配置在/usr/local/etc/apache22/extra/httpd-mpm.conf，但里面根据httpd的工作模式分了很多块，哪一部才是当前httpd的工作模式呢？可通过执行 apachectl -l 来查看： <br/>Compiled in modules: <br/>core.c <br/>prefork.c <br/>http_core.c <br/>mod_so.c<br/><br/>看到prefork 字眼，因此可见当前httpd应该是工作在prefork模式，prefork模式的默认配置是：<br/><br/>1. <IfModule mpm_prefork_module> <br/>2. StartServers 5 <br/>3. MinSpareServers 5 <br/>4. MaxSpareServers 10 <br/>5. MaxClients 150 <br/>6. MaxRequestsPerChild 0 <br/>7. </IfModule><br/><br/>2.要加到多少？<br/><br/>连接数理论上当然是支持越大越好，但要在服务器的能力范围内，这跟服务器的CPU、内存、带宽等都有关系。<br/><br/>查看当前的连接数可以用：<br/><br/>1. ps aux &#124; grep httpd &#124; wc -l<br/><br/>或：<br/><br/>1. pgrep httpd&#124;wc -l<br/><br/>计算httpd占用内存的平均数:<br/><br/>1. ps aux&#124;grep -v grep&#124;awk ‘/httpd/&#123;sum+=$6;n++&#125;;END&#123;print sum/n&#125;’<br/><br/>由于基本都是静态页面，CPU消耗很低，每进程占用内存也不算多，大约200K。<br/><br/>服务器内存有2G，除去常规启动的服务大约需要500M（保守估计），还剩1.5G可用，那么理论上可以支持1.5*1024*1024*1024/200000 = 8053.06368<br/><br/>约8K个进程，支持2W人同时访问应该是没有问题的（能保证其中8K的人访问很快，其他的可能需要等待1、2秒才能连上，而一旦连上就会很流畅）<br/><br/>控制最大连接数的MaxClients ，因此可以尝试配置为：<br/><br/>1. <IfModule mpm_prefork_module> <br/>2. StartServers 5 <br/>3. MinSpareServers 5 <br/>4. MaxSpareServers 10 <br/>5. ServerLimit 5500 <br/>6. MaxClients 5000 <br/>7. MaxRequestsPerChild 100 <br/>8. </IfModule><br/><br/>注意，MaxClients默认最大为250，若要超过这个值就要显式设置ServerLimit，且ServerLimit要放在MaxClients之前，值要不小于MaxClients，不然重启httpd时会有提示。<br/><br/>重启httpd后，通过反复执行pgrep httpd&#124;wc -l 来观察连接数，可以看到连接数在达到MaxClients的设值后不再增加，但此时访问网站也很流畅，那就不用贪心再设置更高的值了，不然以后如果网站访问突增不小心就会耗光服务器内存，可根据以后访问压力趋势及内存的占用变化再逐渐调整，直到找到一个最优的设置值。<br/><br/>(MaxRequestsPerChild不能设置为0，可能会因内存泄露导致服务器崩溃）<br/><br/>更佳最大值计算的公式：<br/><br/>apache_max_process_with_good_perfermance < (total_hardware_memory / apache_memory_per_process ) * 2 <br/>apache_max_process = apache_max_process_with_good_perfermance * 1.5<br/><br/>参考：<br/><br/>apache的参数设置<br/><br/>Apache 2.0性能优化-MPM的选择与配置<br/><br/>如何避免apache的httpd进程占用比较多的内存<br/><br/>对apache中并发控制参数prefork理解和调优<br/><br/>附：<br/><br/>实时检测HTTPD连接数：<br/><br/>1. watch -n 1 -d “pgrep httpd&#124;wc -l”</span></span>
]]>
</description>
</item><item>
<link>https://www.cnmysql.com/post//#blogcomment</link>
<title><![CDATA[[评论] 对apache中并发控制参数prefork理解和调优]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>https://www.cnmysql.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>