监控分析——Web中间件

Posted 小文叔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了监控分析——Web中间件相关的知识,希望对你有一定的参考价值。

发现 中间件监控看是否有性能瓶颈

  核心:主要看中间件的线性池进程池有没有排队情况,请求是否处理及时就OK

Apache

  以前php都是用apache,现在基本用nginx了。

  首先自己启动apache,它的工程路径在/var/www/下面

 1 # ps -ef|grep httpd
 2 root      1319     1  0 00:42 ?        00:00:00 /usr/sbin/httpd
 3 apache    1335  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 4 apache    1336  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 5 apache    1337  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 6 apache    1338  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 7 apache    1339  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 8 apache    1340  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 9 apache    1341  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
10 apache    1342  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd

 首先,切换到httpd的路径:(我们是yum安装的apache,因为编译安装的只有一种工作模式,yum安装才能出来3种工作模式),可以看到三个执行文件,分别是httpd,httpd.event,httpd.worker。分别是apache的三种工作模式,我们默认使用的是httpd这个文件的工作模式。那假设我想用httpd.event的工作模式怎么办呢?把httpd的文件名改成其他的,把httpd.event改成 httpd 。其实默认的httpd本来的名字是 httpd.prefok

所以说有三种模式:.prefok;.event;.worker

我们yum安装的httpd文件会比较分散,主要的是在:/etc/httpd 下面

  conf不用讲,是配置文件夹

  httpd.conf 就是配置文件

我们可以进去查看下:

ServerTokens OS            ##不用管,操作系统版本
ServerRoot "/etc/httpd"    ##apache的安装路径,不用改
PidFile run/httpd.pid      ##在/etc/httpd/run/有一个httpd.pid,这个意思是pidfile会生成在这个路径下。启动的时候这个文件会生成现,这个文件在的话,apache会判定是启动;关闭后这个文件默认会删除,但是如果有时候apache异常关闭,方法不对,会导致这个文件没删除。接下来apache也启动不了,正确做法是手动删除
Timeout 60 ##超时时间,这个超时时间是什么超时???在接收跟发送之前的超时,是请求过来了,tcp/ip连接已经连接了,但是没处理。这个不是connection-timeout,connection-timeout是客户端配置的,客户端发送请求,比如60秒内没连上,就是connection-timeout
KeepAlive Off ##JMeter默认的长链接是on。长链接是啥子东西呢,比如说请求一个页面,用一个链接形成一个链接通道,用这个通道再去send和receive这个请求。复用长链接的话是不同请求页面用之前的那个链接通道,通道会被占住,下次要用的话再继续用这个通道。省去了重新建立链接和关闭链接的过程,但是,链接通道是有限的,占满了的话,其他的请求就不能继续进行链接了
MaxKeepAliveRequests 100 ##最大长链接的请求数,比如说我给300个并发,但是只有100个长链接,代表有200个并发连接不上长链接
KeepAliveTimeout 15 ##长链接的会话保持时间,在这个链接通道内,一个客户端隔了15秒还没发送下一个请求,则长链接就被释放(一般设置3-5秒就够了)
# prefork MPM ##MPM是工作模式,默认为profork
Listen 90 ##对外提供服务的端口号,apache默认为80
LoadModule…….so(一大堆) ##加载的动态库
Include conf.d/*.conf ##把配置文件conf.d文件夹内的以.conf结尾的文件包含进来,可以切换到conf.d文件夹看一看,默认有个welcome.conf,php.conf(php编译后生成的)
User apache ##哪个用户
Group apache ##用户组
ServerAdmin root@localhost
UseCanonicalName Off
DocumentRoot "/usr/local/zentaopms/www" ##工程路径,就是代码往哪儿搁,就往这里放,把安装包往这里放就得了
<Directory "/var/www/html"> ##跟工程路径保持一致
ErrorLog logs/error_log ##日志路径
LogLevel warn ##日志级别,有debug, info, notice, warn, error, crit,alert, emerg可选择。详细点的日志用debug,一般我们用info级别
CustomLog logs/access_log common ##用户日志,一般被注释,可打开

##状态码不同的提示过着提示的路径内容如下,其内容可自行定制:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html

监控的话,把下面俩的注释取消掉:且默认的Allow from .example.com 改成 Allow from all
如果httpd.conf没有以下内容,粘贴进去,就OK也可以加上监听效果
<Location /server-status>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from all
</Location>
ExtendedStatus On ##这一行是详细的监听效果,不需要就不要加就ok
<Location /server-info>
    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from all
</Location>

 

改了。重启

service httpd restart 或者

cd/usr/sbin 下面,执行  ./httpd

接着,看apache有没有启动,然后进入apache的  ip:port/server-status  就可以看到监控的信息(我配置的端口为90),能出来就代表监控成功

http://IP地址:端口/server-status

http://IP地址:端口/server-info

http://IP地址:端口/server-status ?refresh=N  ##N将表示访问状态页面可以每N秒自动刷新一次

还有个是 ip:port/server-info

 

 

现在,我们的apache是prefork工作模式,监控的界面在 ip:port/server-status 如上图,我们看配置文件内的prefork工作模式的配置

# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# ServerLimit: maximum value for MaxClients for the lifetime of the server
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
MaxClients       256
MaxRequestsPerChild  4000
</IfModule>

注意:httpd -l可以知道自己apache的工作模式(worker.c代表worker模式)

# httpd -l
Compiled in modules:
  core.c
  worker.c
  http_core.c
  mod_so.c

 

这里我们可以看一下,apache的进程有几个:

 1 # ps -ef|grep httpd |grep -v grep      ##后面的 -v 是排除掉某些字段,这里我们排除掉本身的 gerp 进程
 2 root      1319     1  0 00:42 ?        00:00:00 /usr/sbin/httpd
 3 apache    1335  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 4 apache    1336  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 5 apache    1337  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 6 apache    1338  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 7 apache    1339  1319  0 00:42 ?        00:00:01 /usr/sbin/httpd
 8 apache    1340  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
 9 apache    1341  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd
10 apache    1342  1319  0 00:42 ?        00:00:00 /usr/sbin/httpd

Prefork:

  很明显,这里显示的 httpd 9个进程,说明,prefork 工作模式是多进程模式,但是apache有8个进程。Prefork MPM是一个非常稳定的模式,Apache在启动之初,会预派生fork一些子进程,然后等待请求进来,并且总会保持一些备用的子进程。同时派生出的每个子进程中只有一个线程,在一个时间点内,只能处理一个请求。Prefork MPM在效率上要比Worker MPM高,但是在内存使用方面也会大很多

  StartServers       8  ##指定服务器启动时建立的子进程数,默认为8,这里我们最好设置为5
  MinSpareServers    5  ##指定空闲子进程的最小数量,默认为5。如当前空闲子进程数小于配置的数量则Apache会以最大每秒一个的速度创建新的子进程。
  MaxSpareServers   20  ##指定空闲子进程的最大数量,默认为20。如果有超过设置的最大进程数则会杀死多余的进程,如果设置的比MinSpareServers小,则Apache会默认修改为MinSpareServers+1
  ServerLimit      256  ##最大是256个线程,如果需要更大就需要加上该参数了。这个参数的最大值是2000,如果需要更大需要编译apache。生效前提:必须放在其他指令的前面
  MaxClients       256  ##每个进程下最大的排队请求数  

  MaxRequestsPerChild  4000  ##这个进程能处理的最大请求数,处理完4000个请求,该进程会被杀死重新启动,防止进程僵死的,如果这进程没处理请求就挂了,用这个可以把进程杀了,如果该值为0,那么这进程一直就不会被杀死

 

  简单看一下网页上的监控信息:

  1 requests currently being processed, 7 idle workers  ##1个正在进行请求的进程,7个空闲的进程

  但有的情况是:1 requests currently being processed, 8 idle workers  那么问题来了,我们设置的初始启动的进程数为8,这里为啥加起来超过8?

那么这就关系到起进程和杀进程的逻辑了。开始我们启动8个进程,那么应该是1+7,永远有一个进程在工作,因为有一个叫做守护进程,它会去检测其他进程的信息,看其他的进程是否是存活的,是否为繁忙的。所以启动之后是1守护+7空闲。

  那么我们设置了,空闲的进程区间为5-20,我们的空闲进程为7,在区间范围内,满足要求。

  那么为啥我们有1+8呢?甚至有的是1+10。其实是有的进程不知道啥时候启动了,有时候有些瞬间,我们有些情况下会变成4个繁忙,4个空闲,而我们最小的空闲为5,那么就会多起一个进程来保证空闲进程数够。就会变成4+5,那么等繁忙的进程变为1,就会变成1+8。apache都是预派的模式,是我进程不够么?不是,我有4个空闲的呢,但是4个空闲的并不满足我的最小要求,怕突然来个大量请求,我满足不了,所以怎样?一旦不满足最小为5的要求,后台赶紧先满足5的最小要求,会启动进程。这就是预派生。所以这情况是正常的,可能是预派生多余了一个进程,但是又不工作,所以多起的那个进程进了idle内,就变成了1+8。

  情况1:start为50,空闲区间为5-20,会有啥情况?

  50=1+49,49>5,满足最小要求,49>20,所以,idle会杀掉为20。最后应该为1+20左右。我们看到结果:由于手速不够快,只能截图到这样:应该从2+28,有一个进程应该是在杀进程。一直杀进程到1+19。

 

 

 

 最后平稳下来为1+19个进程,我们可以看一下:apache 有20个进程

 1 # ps -ef|grep httpd |grep -v grep
 2 root      4402     1  0 07:05 ?        00:00:01 /usr/sbin/httpd
 3 apache    4404  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 4 apache    4407  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 5 apache    4408  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 6 apache    4413  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 7 apache    4414  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 8 apache    4418  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
 9 apache    4420  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
10 apache    4421  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
11 apache    4422  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
12 apache    4423  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
13 apache    4424  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
14 apache    4425  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
15 apache    4426  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
16 apache    4427  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
17 apache    4428  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
18 apache    4429  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
19 apache    4430  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
20 apache    4431  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
21 apache    4432  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd
22 apache    4433  4402  0 07:05 ?        00:00:00 /usr/sbin/httpd

 

我们接着看,网页内:

1 Scoreboard Key:
2 "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
3 "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
4 "C" Closing connection, "L" Logging, "G" Gracefully finishing,
5 "I" Idle cleanup of worker, "." Open slot with no current process

 

  • "_"是等待链接
  • “S”是初始化状态,一般看不到
  • “R”是已经建立了链接,在读请求的过程(在读请求,意味着在排队)
  • “W”是进程接受完,在返回
  • “K”进程是在长链接状态
  • “D”进程处于DNS解析状态
  • “C”是进程链接已完成,请求也发送完成了,在关闭链接的状态
  • “L”是进程在写日志操作
  • “G”是优雅地完成,意思是退出了
  • “I”是杀空闲进程,我们刚刚就有杀空闲进程的操作
  • “.”是连进程都没起

我们刷新,看W是在进程内切换的,说明请求是轮询的,所以在进程内切换。因为我们没用keep-alive,肯定会轮询的

 

那我们看一下,用jmeter进行压测看一下,进程的状态变化,就起10个并发好了:

可以看到,有很多的C和W状态,其实还有R,我没截到图

 

接下来我起,50个并发看看,瞬间爆炸:idle都为0了,说明进程不够了,请求肯定就排队了,空闲都特娘的没有了

 

 看下cpu:平均负载都上天了,us和sy加起来也75,而且mmp的linux巨慢

1 # top
2 top - 07:44:16 up  7:02,  2 users,  load average: 72.83, 18.95, 7.88
3 Tasks: 319 total,   7 running, 312 sleeping,   0 stopped,   0 zombie
4 Cpu(s): 32.5%us, 43.2%sy,  0.0%ni,  0.0%id,  0.0%wa,  6.4%hi, 17.9%si,  0.0%st

 

 

我们的keep-alive是没开启的,接下来,我们开启下keepalive看看:W的进程在一段时间内是不会变化的,因为我们设置了长链接时间

接下来,我们开10个并发:发现很多KKK,这就是keepalive,进程的连接通道的alive

 想看到每个进程的详细信息,可以将 http.conf 内的 ExtendedStatus On 注释取消掉,可以看到每个进程的消耗CPU等

 

总结:有没有排队:看idle数是否小于我们设置的最小空闲数,我们的例子里面就是5;R和W最好一半一半,如果哪个多,说明哪个就有问题,多就意味着在排队

 

WORKER

   Worker模式是多进程多线程模式,使用多个子进程,每个子进程有多个线程。每个线程在某个确定的时间只能维持一个连接。通常来说,在一个高流量的HTTP服务器上Worker MPM是个比较好的选择,因为WorkerMPM的内存使用比Prefork MPM要低得多。但worker MPM也由不完善的地方,假如一个线程崩溃,整个进程就会连同其任何线程一起"死掉".由于线程共享内存空间,所以一个程式在运行时必须被系统识别为"每 个线程都是安全的"。

  多进程多线程

  怎么换worker模式???

  将/user/sbin下的httpd先换成其他名字,比如:httpd.prefork,在把httpd.worker变成httpd

mv httpd httpd.prefork
mv httpd.worker httpd

 

   

改成work模式后,重启apache可能会报错,如下图:

 

 解决方案:安装php-zts

yum -y install php-zts

 

则成功:

看一下工作模式:

# httpd -l
Compiled in modules:
  core.c
  worker.c
  http_core.c
  mod_so.c

 

 说明模式切换完成

 那么假设不是yum的,怎么安装成worker呢?

如果在编译时候不指定,系统默认的是prefork模式。如果需要换成worker模式,需要在编译的时候带上编译参数:--with-mpm=worker

查看apache用的是那种工作模式:在apache安装目录的bin目录下运行:apachectl -l或者httpd -l,如下图:

从图中可以看出apache是work模式

 

配置文件的内容:

 1 # worker MPM
 2 # StartServers: initial number of server processes to start
 3 # MaxClients: maximum number of simultaneous client connections
 4 # MinSpareThreads: minimum number of worker threads which are kept spare
 5 # MaxSpareThreads: maximum number of worker threads which are kept spare
 6 # ThreadsPerChild: constant number of worker threads in each server process
 7 # MaxRequestsPerChild: maximum number of requests a server process serves
 8 <IfModule worker.c>
 9 StartServers         4  ##初始化起几个进程
10 MaxClients         300  ##允许排队的最大链接数,超过300丢弃
11 MinSpareThreads     25  ##最小线程数
12 MaxSpareThreads     75  ##最大线程数
13 ThreadsPerChild     25  ##每个进程下多少个线程
14 MaxRequestsPerChild  0  ##每个进程处理多少个请求就杀死,0代表永远不杀。线程模式杀进程?可能这进程下的其他线程在工作,杀了其他的线程不就完蛋了,所以这里设定为0
15 </IfModule>

ServerLimit 50
//服务器允许配置的进程数上限。值必须大于等于MaxClients/ThreadsPerChild。这个指令和ThreadLimit结合使用配置了MaxClients最大允许配置的数值。任何在重启期间对这个指令的改变都将被忽略,但对MaxClients的修改却会生效。
ThreadLimit 200
//每个子进程可配置的线程数上限。这个指令配置了每个子进程可配置的线程数ThreadsPerChild上限。该值应该跟ThreadsPerChild可能达到的最大值保持一
致,ThreadLimit >= ThreadsPerChild。任何在重启期间对这个指令的改变都将被忽略,但对ThreadsPerChild的修改却会生效。
StartServers 5
//服务器启动时建立的子进程数。
MinSpareThreads 25
//最小空闲线程数, 这个MPM将基于整个服务器监控空闲线程数。假如服务器中总的空闲线程数太少,子进程将产生新的空闲线程。
MaxSpareThreads 500
//配置最大空闲线程数。默认值是"250"。这个MPM将基于整个服务器监控空闲线程数。假如服 务器中总的空闲线程数太多,子进程将杀死多余的空闲线程MaxSpareThreads的取值范围是有限制的。Apache将按照如下限制自动修正您配置
MaxClients 5000
//允许同时伺服的最大接入请求数量(最大线程数量)。任何超过MaxClients限制的请求都将进入等候 队列。因此要增加MaxClients的时候,您必须同时增加 ServerLimit的值。计算公式:MaxClients<=ServerLimit *ThreadsPerChild,将初始值设为(以Mb为单位的最大物理内存/2),然后根据负载情况进行动态调整。比如一台4G内存的机器,那么初始值就是4000/2=2000
ThreadsPerChild 100
//每个子进程建立的常驻的执行线程数,子进程在启动时建立这些线程后就不再建立新的线程了。
MaxRequestsPerChild 0
//配置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。假如MaxRequestsPerChild为"0",子进程将永远不会结束。

将MaxRequestsPerChild配置成非零值有两个好处:
1.能够防止(偶然的)内存泄漏无限进行,从而耗尽内存。
2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。
注意:对于KeepAlive链接,只有第一个请求会被计数。

工作方式:
每个进程能够拥有的线程数量是固定的。服务器会根据负载情况增加或减少进程数量。一个单独的控制进程(父进程)负责子进程的建 立。每个子进程能够建立
ThreadsPerChild数量的服务线程和一个监听线程,该监听线程监听接入请求并将其传递给服务线程处理和应答。Apache总是试图维持一个备 用(spare)或是空闲的服务线程池。这样,客户端无须等待新线程或新进程的建立即可得到处理。在Unix中,为了能够绑定80端口,父进程一般都是以 root身份启动,随后,Apache以较低权限的用户建立子进程和线程。User和Group指令用于配置Apache子进程的权限。虽然子进程必须对 其提供的内容拥有读权限,但应该尽可能给予他较少的特权。另外,除非使用了suexec ,否则,这些指令配置的权限将被CGI脚本所继承。

公式:
ThreadLimit >= ThreadsPerChild
MaxClients = MinSpareThreads+ThreadsPerChild
硬限制:
ServerLimi和ThreadLimit这两个指令决定了活动子进程数量和每个子进程中线程数量的硬限制。要想改变这个硬限制必须完全停止服务器然后再启动服务器(直接重启是不行的)。
Apache在编译ServerLimit时内部有一个硬性的限制,您不能超越这个限制。
prefork MPM最大为"ServerLimit 200000"
其他MPM(包括work MPM)最大为"ServerLimit 20000
Apache在编译ThreadLimit时内部有一个硬性的限制,您不能超越这个限制。
mpm_winnt是"ThreadLimit 15000"
其他MPM(包括work prefork)为"ThreadLimit 20000
注意:
使用ServerLimit和ThreadLimit时要特别当心。假如将ServerLimit和ThreadLimit配置成一个高出实际需要许多的值,将会有过多的共享内存被分配。当配置成超过系统的处理能力,Apache可能无法启动,或系统将变得不稳定。

所以,我们不难理解,初始化是多少个线程?4*25=100个线程,这里面有1个busy,99个idle,那么99>75,所以会杀线程,杀线程不是说杀24个线程,是以进程为单位杀的,杀1个进程,减去25个线程,所以99-25=74,25<74<75.所以会变成1个busy,74个左右的idle.稳定下来应该是1+74

这里应该是误杀了一个线程,25<49<75,也是符合规则的,这个应该可以理解为最小原则?还是说有其他的原因?这个得研究一哈

我们可以试着想一下,如果我将:StartServers         1,初始化进程设为1,那么busy为几?idle为几?

一开始应该是1个busy,24个idle,但是24个idle< 25,那么会再起一个线程,所以会变成1个busy,49个idle

 

 

 那么我们举一个比较极端的例子:

<IfModule worker.c>
StartServers         1
MaxClients         300
MinSpareThreads     25
MaxSpareThreads     25
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

 

 为啥说它极端呢?一开始起1个进程,里面有25个线程,那么会变成1个busy,24个idle,那么就会再起一个进程,变成1个busy,49个idle;49>25,那么会杀一个进程变成24,变成1个busy,24个idle;如此循环往复杀进程起进程?但实际情况真的如此么?实际上

 稳定下来会变成:1个busy,49个dile

为啥呢?因为这时候 MaxSpareThreads 25 这个会失效,默认进程数会+1,所以会变成1个busy,49个idle

 

 总结:worker是多进程多线程模式的,杀跟起都是以进程为单位,空闲线程要在范围内,排队也是一个标准,idle为0或者小于空闲的最小值

 

 

Worker模式监控

(1)第一种情况

初始化4*25=100大于MaxSpareThreads的75,所以要杀掉一个进程,即25个线程,所以最后剩100-25=75,再减掉一个监听线程,最后剩74个空闲线程

(2)第二种情况

初始化3*25=75,即1个守护线程,74个空闲线程,由于小于MinSpareThreads的75,需要再启动一个进程即25个线程,所以最后是1个守护线程,99个空闲线程。有人会问99大于MaxSpareThreads的75,这项不符合。这是因为当实际线程数再校验MinSpareThreads和MaxSpareThreads冲突时,MaxSpareThreads这项配置就失效了,以MinSpareThreads为准

(3)第三种情况

初始化3*30=90,1个守护,89空闲,大于MaxSpareThreads的75,所以要杀掉1个进程即30个线程,最后剩余1个守护,59空闲

(4)第四种情况

 

初始化5*40=200,1个守护,199个空闲,大于MaxSpareThreads的150,杀掉一个进程即40个线程,空闲还有159,还是大于MaxSpareThreads的150,再杀一个进程,空闲变为119,这时却比MinSpareThreads的值还小,再启动一个进程变为空闲变为159又大于MaxSpareThreads,这时就冲突了,MaxSpareThreads就失效了,所以最终是1个守护,159个空闲

 

总结:

如何合理配置apache

1、空闲进程/空闲线程

  要根据实际情况来配置,是要保证并发数,还是要减少内存消耗。如果说系统在大部分时间对并发量要求不高,初始化的的进程/线程数就可以设置的比较少。如果大部分时间系统对并发量要求很高,初始化进程/线程数就可以多配置一点,以免进程/线程频繁的启动和被杀掉,这样更容易消耗系统资源。

2、长连接及其超时时间

  如果用户操作比较频繁,长连接及其超时时间就配大一点,这样就不会频繁的去占用线程和释放线程。如果用户操作不频繁,这时就需要把长连接及其超时时间调小。

3、压测过程的调试

  如果压测过程种发现busy进程/线程数多,空闲进程/线程数少,说明进程/线程都处于比较繁忙状态,通过与初始化的值比较,看看是否需要增大初始化的进程/线程数,以避免频繁的启动和杀进程/线程。反之,如果busy进程/线程数少,空闲进程/线程数多,则需要调小初始化的值,因为空闲进程/线程数多的话会浪费内存。

  响应时间慢,就要考虑中间件线程池是否有排队情况,线程池是否有频繁的创建销毁情况。

4、是否开启gzip压缩(压缩文件图片等)

5、一个进程下面的子线程不宜配置过多,进程下面的一个线程出错可能导致整个进程报错从而导致该进程下的所有线程都不可用。一般一个进程下配置的线程数不要超过250,基本配置从25~250

 

Tomcat

一、配置文件

  路径是在tomcat下的 /conf 文件夹内

二、进行监听:

  tomcat分版本,toncat7比较简单,我这里用的是toncat9,会有些问题,但是可以百度解决。首先进入tomcat页面,点击 “Server Status”,会出现一个登录页面

  

   这里,我们并不知道用户名字和密码是啥,点击“取消”,弹出一个页面,这个页面是配置用户名密码的一个简单说明,这里就比较坑爹了,因为各版本不一样

假设,我们要配置manager-gui的规则,用户名为:tomcat,密码为:secret,要在 conf/tomcat-user.xml 内添加啊这两行:

<role rolename="manager-gui"/>
<user username="tomcat" password="secret" roles="manager-gui"/>

 

 那我们去加加看:这里要注意,不要把这两行加到注释里面去了(xml的注释是:<!--内容-->)

 

 然后重启 tomcat ,会发现 点击“Server Status”,会直接跳到 403

解决办法:把 tomcat 下的 /webapps/manager/META-INF/context.xml 内的这一块注释掉

  再重启 tomcat ,就ok,用刚刚配置的 Manager App 按照我们刚刚设定的账号密码,登陆进去:

 

  页面显示如下:

 

 这里我们选择:Complete Server Status 但是这里的数据很少,按道理讲tomcat 7不会这样,“ajp-nio-8099”数据为空

解决方案:暂无

bio和nio和APR

是tomcat的两个工作模式,tomcat7默认是bio模式,tomcat8以及以上默认是nio的模式。 bio 是最低效率的模式,最少换成 nio 的工作模式

bio:同步模式,阻塞模式,一个线程处理一个请求

nio:利用java的异步io模式,可以通过少量线程处理大量的请求,可减少线程处理请求的等待,tomcat 7要修改 server.xml 文件

<Connector port="8082"protocol="org.apache.coyote.http11.Http11NioProtocol"
               connectionTimeout="20000"
               redirectPort="8443" />

 

apr:Linux需要安装apr和native,这个是利用操作系统的异步io模式去解决io的阻塞问题

Max threads:最大线程数。
Current thread count:最近运行的线程数。 Max processing time:最大CPU时间。 Processing time:CPU消耗总时间。 Request count:请求总数。
Error count:错误的请求数。
Bytes received:接收字节数。
Bytes sent:发送字节数。

 

 

 Max thread:默认200

Current thread count :当前8个线程,busy繁忙 1 个,keep alive 长链接的socket 为1个

Max processing time:最长的处理时间:63ms。有空去了解下这几个配置之间的区别

不难看出,busy的线程接近于Max threads 的情况下,就会有瓶颈