本文主要阐述软件性能测试中的一些调优思想和技术,节选自作者新书《软件性能测试分析与调优实践之路》部分章节归纳。

在国内互联网公司中,Web中间件用的最多的就是Apache和Nginx这两款了,包括很多大型电商网站淘宝、京东、苏宁易购等,都在使用Nginx或者Apache作为Web中间件。而且很多编程语言在做Web开发时,会将Apache或者Nginx作为其绑定的固定组件,比如php语言做Web开发时,就经常和Apache联系在一起,使得apche成为了php在Web开发时的一个标配。而Nginx不管是在作为Web静态资源访问管理或者作为动态的请求代理性能都是非常的高效,当然Nginx或者Apache在性能分析时,有时候也会存在性能瓶颈或者需要进行调优以支持更高的并发处理能力。

1. Nginx的性能分析和调优

1.1  Nginx的负载均衡策略的选择

在一般的时候,Web中间件最大的作用就是负责对请求进行分发,也就是我们常说的起到负载均衡的作用,当然负载均衡只是Nginx的作用之一,Nginx常见的负载均衡策略一般包括轮询、指定权重(weight)、ip_hash、least_conn、fair、url_hash等六种,其中默认执行的策略为轮询,fair、url_hash属于第三方策略,这两种策略不是Nginx自带支持的策略,需要安装第三方的插件来辅助支持。在不同的场景下,每一种策略的选择对系统的整体性能影响都非常大,一般建议根据实际场景和服务器配置来选择对应的负载均衡策略。

  • 轮询策略:Nginx的负载均衡是通过配置upstream来实现请求转发的,在upstream如果没有指定其他任何的策略时,Nginx会自动执行轮询转发策略,upstream中配置每台服务器的权重都一样,会按照顺序依次转发。如下所示就是一个简单的upstream配置,由于配置了192.168.1.14和192.168.1.15两台服务器,所以请求会按照接收到的顺序依次轮询的转发给192.168.1.14和192.168.1.15两台服务器进行执行。Nginx能自动感知转发到的后端服务器是否挂掉,如果挂掉后Nginx会自动将那台挂掉的服务器从upstream中剔除。
upstream applicationServer {

    server 192.168.1.14;

    server 192.168.1.15;

}

使用轮询策略时,其他非必填的辅助参数如下:(转载请注明出处:来源于博客园,作者:张永清 https://www.cnblogs.com/laoqing/p/14259788.html

使用轮询策略的辅助参数

参数

含义

fail_timeout

该参数需要和max_fails参数结合一起来使用,用于表示在fail_timeout指定的时间内某个server允许重试连接失败的最大次数

max_fails

在fail_timeout参数设置的时间内最大失败次数,如果在这个时间内,所有针对该服务器的请求都失败了,Nginx就判定该服务器挂掉了

down

标记指定的服务器已经挂掉了,Nginx将不会再向标记为down的服务器转发任何的请求

  • 指定权重(weight):通过在upstream配置中给相应的服务器指定weight权重参数来实现按照权重分发请求,weight参数值的大小和请求转发比率成正比,一般用于后端应用程序服务器硬件配置差异大而导致承受的访问压力不一样的情况可以使用该配置,配置示例如下:
upstream applicationServer {

    server 192.168.1.14 weight=8;

    server 192.168.1.15 weight=10;

}
  • ip_hash:每个请求按原始访问ip的hash结果来进行请求转发,由于同一个ip的hash值肯定是不变的,这样每个固定客户端就会只访问一个后端应用程序服务器,此种配置一般可以用来解决多个应用程序服务器的session复制和同步的问题,因为同一个ip的请求都转发到了同一台服务器的应用程序上了,所以也就不会有session不同步的问题了,但是可能会导致后端应用服务器的负载不均的情况,因为这种策略下后端应用服务器收到的请求数肯定是很难一样多。配置示例如下:
upstream applicationServer {

ip_hash;

    server 192.168.1.14;

    server 192.168.1.15;

}
  •  least_conn:通过在upstream配置中增加least_conn配置后,Nginx在接收到请求后会把请求转发给连接数较少的后端应用程序服务器,前面讲到的轮询算法是把请求平均的转发给各个后端使它们的负载大致相同,但是有些请求占用的时间很长会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。示例配置如下:
upstream applicationServer {

least_conn;

    server 192.168.1.14;

    server 192.168.1.15;

}
  •  fair:fair属于第三方策略,即不是Nginx本身自带的策略,需要安装对应的第三方插件。fair是按照服务器端的响应时间来分配请求给后端应用程序服务器,响应时间短的优先分配。示例配置如下:
upstream applicationServer {

    server 192.168.1.14;

server 192.168.1.15;

fair;

}
  • url_hash:url_hash同样属于第三方策略,也是需要安装对应的第三方插件。url_hash是按照访问的目标url的hash值来分配请求使同一个url的请求转发到同一个后端应用程序服务器,请求的分发策略和ip_hash有点类似。在做性能调优时主要是适用对缓存命中进行调优,同一个资源(也就是同一个目标url地址)多次请求,可能会到达不同的后端应用程序服务器上会导致不必要的多次下载,使用url_hash后可以使得同一个目标url(也就是同一个资源请求)会到达同一台后端应用程序服务器,这样可以在服务端进行资源缓存再次收到请求后,就可以直接从缓存中读取了。示例配置如下:
upstream applicationServer {

    server 192.168.1.14;

server 192.168.1.15;

hash $request_uri;

}

1.2  Nginx进程数的配置优化

nginx服务启动后会包括两个重要的进程:

  •        master进程:可以控制Nginx服务的启动、停止 、重启、配置文件的重新加载。
  •         worker进程:处理用户请求信息,将收到的用户请求转发到后端应用服务器上。

worker进程的个数可以在配置文件nginx.conf中进行配置,如下所示。

worker_processes  1;  #  Nginx配置文件中worker_processes指令后面的数值代表了Nginx启动后worker进程的个数。

worker进程的数量一般建议等于CPU的核数或者CPU核数的两倍。通过执行lscpu命令可以获取到CPU的核数,如图所示。

或者通过执行grep processor /proc/cpuinfo|wc –l 命令也可以直接获取到CPU的核数。

[root@localhost conf]#grep processor /proc/cpuinfo|wc -l

在配置完worker进程的数量后,还建议将每一个worker进程绑定到不同的CPU核上,这样可以避免出现CPU的争抢。将worker进程绑定到不同的CPU核时可以通过在nginx.conf中增加worker_cpu_affinity 配置,例如将worker进程分配到4核的CPU上,可以按照如下配置进行配置。

worker_processes    4;

worker_cpu_affinity 0001 0010 0100 1000;

1.3  Nginx事件处理模型的优化

为了性能得到最优处理,Nginx的连接处理机制在不同的操作系统中一般会采用不同的I/O事件模型,在Linux操作系统中一般使用epoll的I/O多路复用模型,在freebsd操作系统中使用kqueue的I/O多路复用模型,在solaris操作系统中使用/dev/pool方式的I/O多路复用模型,在windows操作系统中使用的icop模型。在实际使用Nginx时,我们也是需要根据不同的操作系统来选择事件处理模型,很多事件模型都只能在对应的操作系统上得到支持。比如我们在Linux操作系统中,可以使用如下配置来使用epoll事件处理模型。

events {
worker_connections 1024;
use epoll;
}

关于I/O多路复用做个说明:在Nginx中可以配置让一个进程处理多个I/O事件和多个调用请求,这种处理方式就类似Redis中的单线程处理模式一样,Redis缓存读写处理时采用的虽然是单线程,但是性能和效率却是非常的高,这就是因为Redis采用了异步非阻塞I/O多路复用的策略导致资源的开销很小,不需要重复的去创建和释放资源,而是共用一个处理线程。Nginx中也同样采用异步非阻塞I/O策略,每个worker进程会同时启动一个固定的线程来利用epoll监听各种需要处理的事件,当有事件需要处理时会将事件注册到epoll模型中去进行处理,异步非阻塞I/O策略在处理时线程可以不用因为某个I/O的处理耗时很长而一直导致线程阻塞等待,线程可以不用等待响应,也不必等待响应,而是可以继续去处理其他的I/O事件。当I/O事件处理完成后,操作系统内核会通知I/O事件已经处理完成,这时线程才会去获取处理好的结果。

下面表列出了Nginx常用事件处理模型的详细介绍。

Nginx常用事件处理模型

处理模型

说明

select

各个版本的Linux和Windows操作系统都支持的基本事件驱动模型。select模型处理事件的步骤:

(1)、创建事件的描述符集合,包括读、写、异常发送三类事件描述符分别用来收集读事件的描述符、写事件的描述符和异常事件的描述符。

(2)、调用select模型底层提供的select函数等待事件发生。

(3)、轮询所有事件描述符集合中的每一个事件描述符,检查是否有相应的事件发生,如果有,select模型就进行相关的处理。

poll

Linux操作系统上的基本事件驱动模型,此模型无法在windows操作系统上使用。poll与select的共同点是都是先创建一个关注事件的描述符集合,再去等待这些事件发生,然后再轮询描述符集合检查有没有事件发生,如果有就进行处理。不同点是select库需要为读事件、写事件、异常事件分别创建一个描述符集合,因此在最后轮询的时候,需要分别轮询这三个集合。而poll库只需要创建一个集合,在每个描述符对应的结构上分别设置读事件、写事件、异常事件,最后轮询的时候,可以同时检查这三种事件是否发生

epoll

epoll库是Nginx服务器支持的高性能事件驱动模型之一,epoll属于poll模型的一个变种,和poll主要区别在于epoll不需要使用轮询的模式去检查有没有对应的事件发生,而是交给操作系统内核去负责处理,一旦有某种对应的事件发生时内核会把发生事件的描述符列表通知给进程,这样就避免了轮询整个描述符列表。epoll库在Linux操作系统上是非常高效的,epoll可以同时处理的I/O事件数是操作系统可以打开文件的最大数目,而且epoll库的I/O效率不随描述符数目增加而线性下降,因为它只会对操作系统内核反馈的待处理的事件描述符进行操作

rtsig

rtsig模型不是一种经常用到的事件处理模型,rtsig模型在工作时会通过系统内核建立一个rtsig队列用于存放标记事件发生的信号,每个事件发生时,系统内核就会产生一个信号存放到rtsig队列中等待Nginx工作进程的处理

kqueue

Kqueue模型也是poll模型的一个变种,和上面介绍的epoll模型的处理方式几乎一样,都是通过避免轮询操作提供效率。该模型支持在BSD系列操作系统(例如FreeBSD 、OpenBSD 、NetBSD 等)上使用

/dev/poll

/dev/poll模型一般用于solaris操作系统或者其他的unix衍生操作系统上,该模型最早是Sun公司在开发Solaris系列平台时提出的用于完成事件驱动机制的方案,它使用了虚拟的/dev/poll设备,开发人员可以将要监视的文件描述符加入这个设备,然后通过调用ioctl()函数来获取事件通知

eventport

该模型也是Sun公司在开发Solaris系列平台时提出的、用于完成事件驱动机制的方案,它可以有效防止内核崩溃情况的发生,Nginx在此基础上提供了事件处理支持,但是由于Solaris自身后来的没落,所以该模型现在也很少使用。

1.4  Nginx客户端连接数的优化

在高并发的请求调用中,连接数有时候很容易成为性能的一个瓶颈,Nginx中可以通过如下方式来调整Nginx的连接数。

  • 配置Nginx单个进程允许的客户端最大连接数:可以通过修改Nginx的nginx.conf配置文件中的如下配置:
events        #可以设置Nginx的工作模式以及连接数上限
{
worker_connections 1024;
}
  • 配置Nginx worker进程可以打开的最大文件数:可以通过修改Nginx的nginx.conf配置文件中的如下配置:
worker_processes  2;
worker_rlimit_nofile 2048; # 设置worker进程可以打开的文件数
  • Linux内核的优化:Linux操作系统的/etc/sysctl.conf配置文件中可以重新配置很多Linux系统的内核参数  

1.5  Nginx中文件传输的优化

Nginx中文件传输一般需要优化的是如表中所示的几个参数。

Nginx文件传输需要优化的参数

Nginx参数

说明

tcp_nopush

tcp_nopush和tcp_nodelay是互斥的,开启tcp_nopush后会设置调用tcp_cork方法,让数据包不会马上传送出去,等到数据包累积到最大时,一次性的传输出去,这样有助于解决网络堵塞,从而提供网络传输的性能,默认为off。设置为on时的配置如下:

tcp_nopush on;

tcp_nodelay

和tcp_nopush的处理方式刚好相反,在开启了tcp_nodelay后意味着无论数据包是多么的小,都立即发送出去,默认值为on,设置为off时为关闭,配置的方式如下:

tcp_nodelay off;

sendfile

sendfile 一般和tcp_nopush选项搭配在一起使用。Nginx中提供 sendfile 选项用来提高服务器性能,sendfile实际上是 Linux2.0版本以后推出的一个系统调用。在网络文件传输过程中一般是:从硬盘读写 → 写入操作系统内核 buffer → 读入用户模式 buffer-> 写入内核socket buffer →协议栈开始传输,在开启了sendfile后,之前的传输步骤就简化成了:从硬盘读写 → 写入内核 buffer (数据可以快速拷贝到内核 socket buffer) →协议栈开始传输,这就是常说的零拷贝方式。开启sendfile的配置如下:

sendfile on;

nginx gzip压缩相关参数:

gzip on

gzip_min_length

gzip_buffers

gzip_http_version

gzip_comp_level

gzip_types

gzip_vary

gzip_proxied off

gzip on:开启gzip 压缩模式

gzip_min_length :设置允许压缩的页面最小宇节数,字节数大小 从HTTP请求的header头部的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩。一般建议设置成gzip_min_length 1K,因为如果小于1K可能会越压越大。

gzip_buffers:表示压缩缓冲区大小,例如设置gzip_buffers  4 16k; 表示申请4个单位为16K的内存作为压缩结果数据流的缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。

gzip_http_version:表示压缩的HTTP协议版本,默认为1.1,常用的浏览器几乎都支持gzip解压,一般使用默认设置即可。

gzip_comp_level:表示gzip的压缩比率,该参数用来指定gzip压缩比,可以设置为1-9之间的数字。1表示压缩比最小但是压缩处理速度最快,9表示压缩比最大并且传输速度快,但处理时耗时最长也比较消耗CPU资源。该参数一般建议根据实际场景中传输的大部分文件大小来设置,在压缩处理速度和压缩比率大小之间做到均衡。

gzip_types:用来设置指定压缩的类型(就是HTTP协议中的Content-Type属性中的媒体类型), 支持的常见类型包括 text/plain、application/x-javascript 、text/css、 application/xml、application/json等。

gzip_vary:表示启用response header头部属性“Vary:Accept-Encoding”的压缩模式。[z1]

zip_proxied off:默认为off,一般在Nginx作为反向代理的时候启用,表示对代理的结果数据进行压缩,zip_proxied可以在后面增加参数来判断HTTP的header头部中符合指定条件后才进行数据压缩。

loff :关闭所有的代理结果数据的压缩。

lexpired :启用压缩,如果header头部中包含 "Expires" 头信息。

lno-cache:启用压缩,如果header头部中包含 "Cache-Control:no-cache" 头信息。

lno-store:启用压缩,如果header头部中包含 "Cache-Control:no-store" 头信息。

lprivate:启用压缩,如果header头部中包含"Cache-Control:private" 头信息。

lno_last_modified:启用压缩,如果header头部中不包含 "Last-Modified" 头信息。

lno_etag:启用压缩,如果header头部中不包含 "ETag" 头信息。

lauth:启用压缩,如果header头部中包含 "Authorization" 头信息。

lany:表示总是启用压缩,表示会对返回的代理数据都进行压缩。


[z1]

在nginx.conf配置文件中开启sendfile参数的方式配置示例如下:

sendfile on ;#默认情况下,sendfile是off。

  

在nginx.conf配置文件中开启tcp_nopush参数的方式配置示例如下:

tcp_nopush on ;#默认情况下tcp_nopush是off

  

在nginx.conf配置文件中开启tcp_nodelay参数的方式配置示例如下:

tcp_nodelay on;#默认情况下tcp_nodelay是on

1.6  Nginx中FastCGI配置的优化

FastCGI是在CGI基础上的优化升级,CGI是Web服务器与CGI程序间传输数据的一种标准,运行在服务器上的CGI程序按照这个协议标准提供了传输接口,具体介绍如下。

  • CGI:CGI是英文common gateway interface的简写,翻译过来就是通用网关接口,这套接口描述了Web服务器与同一计算机上的软件的通信方式,有了CGI标准后集成了CGI的Web服务器就可以通过CGI接口调用服务器上各种动态语言实现的程序了,这些程序只要通过CGI标准提供对应的调用接口即可。CGI的处理的一般流程如图所示。

  • l         FastCGI:FastCGI是一个传输快速可伸缩的用于HTTP服务器和动态脚本语言间通信的接口,它为所有Internet应用程序提供了高性能,而不受Web服务器API的限制。包括Apache、Nginx在内的大多数Web服务都支持FastCGI,同时FastCGI也被许多脚本语言(例如Python、PHP等)所支持。

Nginx本身并不支持对外部动态程序的直接调用或者解析,所有的外部编程语言编写的程序(比如Python、PHP)必须通过FastCGI接口才能调用。FastCGI相关参数说明如表所示。

FastCGI相关参数说明

Nginx FastCGI相关参数

说明

fastcgi_connect_timeout

用于设置Nginx服务器和后端FastCGI程序连接的超时时间,默认值值为60秒,一般建议不要超过75秒,时间太长会导致高并发调用下建立连接过多而不能及时释放,建立的连接越多消耗的资源就会越多

fastcgi_send_timeout

用于设置Nginx发送CGI请求到FastCGI程序的超时时间,这个超时时间不是整个请求的超时时间,而是两个成功请求的之间间隔时间为超时时间,如果这个时间内FastCGI服务没有收到任何信息连接将被关闭

fastcgi_read_timeout

用于设置Nginx从FastCGI服务器读取响应信息的超时时间,连接建立成功后 Nginx等待后端FastCGI程序的响应时间,实际上是读取FastCGI响应成功消息的间隔时间,如果这个时间内Nginx没有再次从FastCGI读取到响应消息连接就会被关闭

fastcgi_buffer_size

用于设置Nginx FastCGI的缓冲区的大小,缓冲区大小表示的是读取从FastCGI程序端收到的第一部分响应信息的缓冲区大小,这里的第一部分通常会包含一个小的响应头部消息,默认情况下这个参数的大小等价于操作系统的1个内存页单位的大小,一般是4k或者8k, 在不同的操作系统上默认大小可能不同

fastcgi_buffers

用于设置Nginx用多少和多大的缓冲区读取从FastCGI程序收到的响应信息,默认值为fastcgi_buffer 8 4k|8k;可以在nginx.conf配置文件的的http、server、location这三个字段中使用。

一般用于指定Web服务器本地需要用多少和多大的缓冲区来缓冲FastCGI的应答请求,比如如果一个fastcgi程序的响应消息大小为12k,那么配置为fastcgi_buffers 6 4k时将分配3个4k的buffer

fastcgi_busy_buffers_size

用于设置服务器很忙时可以使用的fastcgi_buffers大小,一般推荐的大小为fastcgi_buffers*2;默认值为 fastcgi_busy_buffers_size 8k|16k

fastcgi_temp_file_write_size

用于设置FastCGI临时文件的大小,一般建议可以设置为128~256KB ,默认大小为fastcgi_temp_file_write_size 8k|16k;

fastcgi_cache myboy_nginx

用于设置开启FastCGI缓存功能并为其指定一个名称(比如指定为myboy_nginx)。开启缓存可以有效降低CPU的负载并且可以防止HTTP请求的502错误(HTTP服务器端的一个错误码,一般是指上游服务器接收到无效的响应)的发生,而且合理设置该参数可以有效的提高请求的并发数和tps

fastcgi_cache_path

用于设置fastcgi_cache的缓存路径。

例如可以设置为:fastcgi_cache_path /opt/data/nginx/cache levels = 2:2 keys_zone = nginx_ fastcgi_cache:256m inactive = 2d max_size=80g    use_temp_path=on;fastcgi_cache的缓存路径可以设置目录前列层级,比如2:2会生成256*256 个子目录,keys_zone是设置这个缓存空间的名字以及使用多少物理内存(一般经常被访问的热点数据Nginx会直接放入内存以提高访问速度),nginx_ fastcgi _cache:256m表示缓存空间的名字为nginx_ fastcgi_cache,大小为256m。inactive表示默认失效时间,max_size表示最多用多少硬盘空间来存储缓存,特别要注意的是fastcgi_cache缓存是先写在fastcgi_temp_path,等到达一定大小后再移到fastcgi_cache_path下去的,所以这个两个目录最好在同一个磁盘分区下以提高I/O读写速度, 如果设置use_temp_path=off则 nginx 会将缓存文件直接写入指定的 cache 文件中

fastcgi_temp_path

用于设置fastcgi_cache的临时目录路径,例如可以设置为fastcgi_temp_path /usr/local/nginx/fastcgi_temp

fastcgi_cache_valid

用于对不同的HTTP 请求响应状态码设置缓存的时长。

例如:fastcgi_cache_valid 200 302 lh;

表示将HTTP 请求响应状态码为200和302的应答缓存1个小时。

再例如:fastcgi_cache_valid 301 2d;

表示将HTTP 请求响应状态码为301的应答缓存2天

fastcgi_cache_min_uses

用于设置同一请求达到几次之后晌应消息将被缓存。

例如:fastcgi_cache_min_uses 1;1表示一次即被缓存

fastcgi_cache_use_stale

用于设置哪些状态下使用过期缓存。

例如:fastcgi_cache_use_stale error timeout invalid_header http_500 表示在发生error错误、响应超时、HTTP的请求头无效和HTTP请求返回状态码为500时使用过期缓存

fastcgi_cache_key

用于设定fastcgi_cache中的key值。

例如:fastcgi_cache_key  scheme$request_method$host$request_uri

表示以请求的URI作为缓存的key,Nginx会取这个key的md5作为缓存文件,如果设置了缓存的目录,Nginx会从后往前取对应的位数作为目录。建议一定要加上$request_method变量一起作为cache key,防止如果先请求的为head 类型(HTTP请求的一种类型,类似于get请求,只不过返回的响应中没有具体的响应内容,仅用于获取响应报文的头部信息),后面的GET请求将返回为空

1.7  Nginx的监控

Nginx自带了监控模块,但是需要在Nginx编译安装时指定安装监控模块,默认情况下是不会安装该监控模块的,需要指定的编译参数为--with-http_stub_status_module。

编译安装完成后,Nginx的配置文件nginx.conf中还是不会开启监控,需要在配置文件中增加如下配置,其中allow 192.168.1.102代表允许访问监控页面的ip地址,如图所示。

location = /nginx_status {
stub_status on;
access_log off;
allow 192.168.1.102;
deny all;
}

  

修改完配置文件后,通过执行nginx –s reload来重新加载配置信息,然后通过访问http://nginx服务器ip地址:端口号/nginx_status 就可以进入监控页面了,如图所示。

从图中可以看到当前已经建立的连接数、服务器已经接收的请求数、请求的处理情况等监控信息。

2、Apache的性能分析和调优

在Web中间件中除了Nginx外另一个用的最多的中间件就是Apache了,Apache几乎可以运行在所有的操作系统中,支持HTTP、SSL、Socket、FastCGI、SSO、负载均衡、服务器代理等很多功能模块,在性能测试分析中如果对Apache使用不当,那么Apache有时候也可能会成为高并发访问的瓶颈。

2.1  Apache的工作模式选择和进程数调优

Apache的工作模式主要是指Apache在运行时内存分配、CPU、进程以及线程的使用管理和请求任务的调度等。Apache比较稳定的工作模式有prefork模式、worker模式、event模式,这三种模式也是Apache经常使用的模式。Apache默认使用的是prefork模式,一般可以在编译安装Apache时通过参数--with-mpm来指定安装后使用的工作模式。

可以通过执行httpd –V命令来查看Apache当前使用的工作模式,如图所示可以看到当前的工作模式为默认的prefork模式。

1. prefork模式

prefork是Apache的默认工作模式,采用非线程型的预派生方式来处理请求,在工作时使用多进程,每个进程在同一个固定的时间只单独处理一个连接,这种方式效率高但由于是多进程的方式所以内存使用比较大。如图所示,可以看到prefork模式下启动了多个进程。

prefork工作模式在收到请求后的处理过程如图所示,从图中可以看到处理过程是单进程和单线程的方式,由于不存在线程安全问题所以这种模式非常适合于没有线程安全库,需要避免线程安全性问题的系统。虽然解决了线程安全问题,但是也必然会导致无法处理高并发请求的场景,prefork模式会将请求放进队列中,一直等到有可用子进程请求才会被处理,也很容易导致请求队列积压。

prefork工作模式主要的配置参数如表所示。

<IfModule mpm_prefork_module>
StartServers 8
MinSpareServers 8
MaxSpareServers 10
MaxRequestWorkers 512
MaxConnectionsPerChild 1000
</IfModule>  

表 prefork工作模式主要的配置参数说明

参数

说明

StartServers

启动的server进程个数,也就是启动多少个子进程来处理请求,默认值为5

MinSpareServers

空闲子进程的最小数量,默认值为5,如果当前空闲子进程数少于MinSpareServers ,那么Apache会以最大每秒一个的速度产生新的子进程。一般不建议参数设置的过大,可以根据实际的并发请求量来进行设置

MaxSpareServers

空闲子进程的最大数量,默认值为10。如果当前有超过MaxSpareServers数量的空闲子进程,那么主进程会杀死多余的子进程

MaxRequestWorkers

代表服务器在同一时间内可以处理客户端发送的最大请求数量,默认是256。当超过了MaxRequestWorkers大小限制的请求就会进入等待队列进行排队

MaxConnectionsPerChild

每个子进程在其生命周期内允许接收处理的最大请求数量。如果请求总数已经达到这个数值,子进程将会结束,在有新的请求时就会重新开启新的子进程。如果设置为0,子进程将永远不会结束。该值不宜设置的过小,过小的话会容易导致进程频繁的开启和关闭,引起CPU的上下文切换过多。当然也建议不要设置为0,非0的情况下由于子进程肯定都存在生命周期,这样可以防止内存泄漏以及有效的快速释放不能释放的资源

2. worker模式

worker模式使用了多进程和多线程相结合的混合模式来处理请求,如图所示work模式下也是主进程会首先派生出一批子进程,但和prefork模式不同的是work模式下每个子进程会创建多个线程,每个请求会分配给一个不同的线程处理。work模式中处理请求时由于采用了多线程的处理方式,所以高并发下处理能力会更强,但是由于是多线程处理方式,所以这种模式下需要考虑线程安全问题。

转载请注明出处:来源于博客园,作者:张永清 https://www.cnblogs.com/laoqing/p/14259788.html

worker工作模式主要的配置参数如表所示。

<IfModule mpm_worker_module>
StartServers 4
ServerLimit 20
MinSpareThreads 65
MaxSpareThreads 256
ThreadsPerChild 30
MaxRequestWorkers 410
MaxConnectionsPerChild 1200
</IfModule>

表 worker工作模式主要的配置参数说明

参数

说明

StartServers

Apache服务启动时初始启动的子进程数量,在workers模式下默认是3

ServerLimit

系统允许启动的最大进程数量

MinSpareThreads

服务器保持启动的最小线程数

MaxSpareThreads

服务器保持启动的最大线程数

ThreadsPerChild

每个子进程允许启动的线程数

MaxRequestWorkers /MaxClients

代表服务器在同一时间内可以处理客户端发送的最大请求数量

MaxConnectionsPerChild

和prefork工作模式一样,代表每个子进程在其生命周期内允许接收处理的最大请求数量。如果请求总数已经达到这个数值,子进程将会结束,在有新的请求时就会重新开启新的子进程。如果设置为0,子进程将永远不会结束

转载请注明出处:来源于博客园,作者:张永清 https://www.cnblogs.com/laoqing/p/14259788.html

3. event模式

event模式和worker工作模式有点类似,在event工作模式中会有一些专门的线程来承担管理和分配线程的工作,通过这种方式使event工作模式解决了HTTP请求 keep-alive长连接的时候占用线程资源被浪费的问题,因为会有一些专门的线程用来管理这些keep-alive类型的工作线程,当有真实请求过来的时候,将请求传递给服务器端可用的工作线程进行处理,处理完毕后又允许其释放资源。如图所示。

event工作模式主要的配置参数如下:

<IfModule mpm_event_module>
StartServers 3
ServerLimit 16
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 1000
</IfModule>

event工作模式的配置参数几乎与worker模式是一样的,因为event模式本身就是对worker模式的一种升级改进。

2.2  Apache的mod选择和优化

未完待续,更多内容  

备注:作者的原创文章,转载须注明出处。原创文章归作者所有,欢迎转载,但是保留版权。对于转载了博主的原创文章,不标注出处的,作者将依法追究版权,请尊重作者的成果。

关于软件性能分析调优,可以加微信号yq597365581或者微信号hqh345932,进入专业的性能分析调优群进行交流沟通。

软件性能测试分析与调优实践之路-Web中间件的性能分析与调优总结的更多相关文章

  1. 软件性能测试分析与调优实践之路-Java应用程序的性能分析与调优-手稿节选

    Java编程语言自从诞生起,就成为了一门非常流行的编程语言,覆盖了互联网.安卓应用.后端应用.大数据等很多技术领域,因此Java应用程序的性能分析和调优也是一门非常重要的课题.Java应用程序的性能直 ...

  2. 软件性能测试分析与调优实践之路-JMeter对RPC服务的性能压测分析与调优-手稿节选

    一.JMeter 如何通过自定义Sample来压测RPC服务 RPC(Remote Procedure Call)俗称远程过程调用,是常用的一种高效的服务调用方式,也是性能压测时经常遇到的一种服务调用 ...

  3. MySQL数据库的性能分析 ---图书《软件性能测试分析与调优实践之路》-手稿节选

    1  .MySQL数据库的性能监控 1.1.如何查看MySQL数据库的连接数 连接数是指用户已经创建多少个连接,也就是MySQL中通过执行 SHOW  PROCESSLIST命令输出结果中运行着的线程 ...

  4. Hadoop作业性能指标及參数调优实例 (三)Hadoop作业性能參数调优方法

    作者: Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Had ...

  5. 高并发场景下JVM调优实践之路

    一.背景 2021年2月,收到反馈,视频APP某核心接口高峰期响应慢,影响用户体验. 通过监控发现,接口响应慢主要是P99耗时高引起的,怀疑与该服务的GC有关,该服务典型的一个实例GC表现如下图: 可 ...

  6. jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——总结与性能分析

    Sizzle引擎的主体部分已经分析完毕了,今天为这部分划一个句号. a. Sizzle解析流程总结 是时候该做一个总结了.Sizzle解析的流程已经一目了然了. 1.选择器进入Sizzle( sele ...

  7. WEB网站前端性能分析相关

    现在的网站分析工具,数据源主要有两种,分别是服务器日志(WebServer Log)和采集日志 买 优化要根据具体的业务和场景来分析 埋点:监控用户点击的每一步

  8. PHP 性能分析第三篇: 性能调优实战

    注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或  PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 ...

  9. 系统级性能分析工具perf的介绍与使用

    测试环境:Ubuntu16.04(在VMWare虚拟机使用perf top存在无法显示问题) Kernel:3.13.0-32 系统级性能优化通常包括两个阶段:性能剖析(performance pro ...

随机推荐

  1. caffe源码 理解链式法则

    网络结构 首先我们抽象理解下一个网络结构是怎样的,如下图所示 F1,F2,F3为某种函数 input为输入数据,output为输出数据 X1,X2为为中间的层的输入输出数据 总体来说有以下关系 X1 ...

  2. AcWing 326. XOR和路径

    大型补档计划 题目链接 如果整体来做,发现既有加法,也有整体异或,这样不容易搞. 考虑异或,各个位置互不干扰,按位考虑一下. 枚举每一位 \(k\) 发现如果设 \(f[u]\) 为这一位的期望结果还 ...

  3. Android FART脱壳机流程分析

    本文首发于安全客 链接:https://www.anquanke.com/post/id/219094 0x1 前言 在Android平台上,程序员编写的Java代码最终将被编译成字节码在Androi ...

  4. nginx 静态化合集(去掉index.php目录)

    访问某域名时,去掉index.php目录时达到效果一样 如:www.test1/index.php/test2跟www.test1/test2效果一致 在vhosts.conf中加重写就可以了 loc ...

  5. vue2中$emit $on $off实现组件之间的联动,绝对有你想了解的

    在vue2开发中,你肯定会遇到组件之间联动的问题,现在我们就来说说哪个神奇的指令可以满足我们的需求. 一.先上实例: 需求:点击A组件或者B组件可以使C组件的名称相应发生改变,同样,点击A组件也会使对 ...

  6. 配置nginx支持THINKPHP的PATH_INFO

    ThinkPHP支持通过PATHINFO和URL rewrite的方式来提供友好的URL,但是Nginx中默认是不支持PATHINFO的,所以我们需要修改nginx.conf文件. location ...

  7. Linux OOM Killer造成数据库访问异常排查

    服务器上的服务器访问异常,查看/va/log/messages发现如下: Sep 22 16:08:21 safeserver kernel: java invoked oom-killer: gfp ...

  8. 6 个例子教你重构 Python 代码

    1. 合并嵌套的 if 条件 太多的嵌套会使代码难以理解,这在 Python 中尤为如此,因为 Python 没有括号来帮助区隔不同的嵌套级别. 阅读深度嵌套的代码容易让人烦躁,因为你必须理清哪些条件 ...

  9. Python写一个对象,让它自己能够迭代

    仿写range()对象,对象是可迭代的: 1 #!usr/bin/env python3 2 # -*- coding=utf-8 -*- 3 4 class myRange(): 5 #初始化,也叫 ...

  10. Nacos(一)源码分析Nacos注册示例流程

    nacos官方地址:https://nacos.io/zh-cn/ 大家可以看一下nacos的中文手册以及官方源码,博主就不带领大家快速入门 了,官方文档中都有而且非常标准,比其他博客写的好多了并且还 ...