nginx-面试篇-11

nginx性能优化

当我需要进行性能优化时,说明我们服务器无法满足日益增长的业务。性能优化是一个比较大的课题,需要从以下几个方面进行探讨

  • 当前系统结构瓶颈

  • 了解业务模式

  • 性能与安全

当前系统结构瓶颈

首先需要了解的是当前系统瓶颈,用的是什么,跑的是什么业务。里面的服务是什么样子,每个服务最大支持多少并发。比如针对Nginx而言,我们处理静态资源效率最高的瓶颈是多大?

可以通过查看当前cpu负荷,内存使用率,进程使用率来做简单判断。还可以通过操作系统的一些工具来判断当前系统性能瓶颈,如分析对应的日志,查看请求数量。也可以通过nginx http_stub_status_module模块来查看对应的连接数,总握手次数,总请求数。也可以对线上进行压力测试,来了解当前的系统的性能,并发数,做好性能评估。

了解业务模式

虽然我们是在做性能优化,但还是要熟悉业务,最终目的都是为业务服务的。我们要了解每一个接口业务类型是什么样的业务,比如电子商务抢购模式,这种情况平时流量会很小,但是到了抢购时间,流量一下子就会猛涨。也要了解系统层级结构,每一层在中间层做的是代理还是动静分离,还是后台进行直接服务。需要我们对业务接入层和系统层次要有一个梳理。

性能与安全

性能与安全也是一个需要考虑的因素,往往大家注重性能忽略安全或注重安全又忽略性能。比如说我们在设计防火墙时,如果规则过于全面肯定会对性能方面有影响。如果对性能过于注重在安全方面肯定会留下很大隐患。所以大家要评估好两者的关系,把握好两者的孰重孰轻,以及整体的相关性。权衡好对应的点。

系统与nginx性能优化

大家对相关的系统瓶颈及现状有了一定的了解之后,就可以根据影响性能方面做一个全体的评估和优化。

  • 网络(网络流量、是否有丢包,网络的稳定性都会影响用户请求)
  • 系统(系统负载、饱和、内存使用率、系统的稳定性、硬件磁盘是否有损坏)
  • 服务(连接优化、内核性能优化、http服务请求优化都可以在nginx中根据业务来进行设置)
  • 程序(接口性能、处理请求速度、每个程序的执行效率)
  • 数据库、底层服务

上面列举出来每一级都会有关联,也会影响整体性能,这里主要关注的是Nginx服务这一层。

文件句柄

在linux/unix操作系统中一切皆文件,我们的设备是文件,文件是文件,文件夹也是文件。当我们用户每发起一次请求,就会产生一个文件句柄。文件句柄可以简单的理解为文件句柄就是一个索引。文件句柄就会随着请求量的增多,进程调用频繁增加,那么产生的文件句柄也就会越多。

系统默认对文件句柄是有限制的,不可能会让一个进程无限制的调用句柄。因为系统资源是有限的,所以我们需要限制每一个服务能够使用多大的文件句柄。操作系统默认使用的文件句柄是1024个句柄。

设置方式

  • 系统全局性修改

  • 用户局部性修改

  • 进程局部性修改

系统全局性修改和用户局部性修改

在linux中每个服务都对应有一个用户在运行这个服务,例如:

nginx     nginx

ftp         ftp

[root@localhost ~]# vim /etc/security/limits.conf
.....
#<domain>      <type>  <item>         <value>
  用户           类型     资源            值  
 
#*               soft    core            0
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4
 

type:有 soft,hard 和 -,soft 指的是当前系统生效的设置值。hard 表明系统中所能设定的最大值。soft 的限制不能比hard限制高。用 - 就表明同时设置了 soft 和 hard 的值。

soft:软控制,到达设定值后,操作系统不会采取措施,只是发提醒

hard:硬控制,到达设定值后,操作系统会采取机制对当前进程进行限制,这个时候请求就会受到影响

资源:
core - 限制内核文件的大小
date - 最大数据大小
fsize - 最大文件大小
memlock - 最大锁定内存地址空间
nofile - 打开文件的最大数目
rss - 最大持久设置大小
stack - 最大栈大小
cpu - 以分钟为单位的最多 CPU 时间
nproc - 进程的最大数目
as - 地址空间限制
maxlogins - 此用户允许登录的最大数目

root:这里代表root用户(系统全局性修改)

*:代表全局,即所有用户都受此限制(用户局部性修改)
nofile:打开文件的最大数目。后面的数字即设定的值,一般设置10000左右

可以看到root和*,root代表是root用户,*代表的是所有用户,后面的数字就是文件句柄大小。大家可以根据个人业务来进行设置。

在企业新装的系统,这个地方应该根据实际情况进行设置,可以设置全局的,也可以设置用户级别的

要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中

[root@localhost ~]# vim /etc/pam.d/login

 sysctl -p 使配置生效。

进程局部性修改

worker_rlimit_nofile 是在进程上面进行限制。每个进程的最大文件打开数,最好与ulimit -n的值保持一致。

user  nginx;
worker_processes  1;  
 
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
 
worker_rlimit_nofile 65535; #进程限制
 
events {
    worker_connections  1024; #最大连接数
}
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '"$args" "$request_uri"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on; 
    #tcp_nopush     on; 
 
    keepalive_timeout  65; 
 
    #gzip  on; 
 
    include /etc/nginx/conf.d/*.conf;
}

扩展—ulimit

-a  显示目前资源限制的设定。
-c <core文件上限>  设定core文件的最大值,单位为区块。
-d <数据节区大小>  程序数据节区的最大值,单位为KB。
-f <文件大小>  shell所能建立的最大文件,单位为区块。
-H  设定资源的硬性限制,也就是管理员所设下的限制。
-m <内存大小>  指定可使用内存的上限,单位为KB。
-n <文件数目>  指定同一时间最多可开启的文件数。
-p <缓冲区大小>  指定管道缓冲区的大小,单位512字节。
-s <堆叠大小>  指定堆叠的上限,单位为KB。
-S  设定资源的弹性限制。
-t <CPU时间>  指定CPU使用时间的上限,单位为秒。
-u <程序数目>  用户最多可开启的程序数目。
-v <虚拟内存大小>  指定可使用的虚拟内存上限,单位为KB
资源:

#-core-限制核心文件大小(KB)
 
#-data-最大数据大小(KB)
 
#-fsize-最大文件大小(KB)
 
#-memlock-max locked in memory address space(KB)
 
#-nofile-打开文件描述符的最大数目
 
#-rss-最大常驻集大小(KB)
 
#-stack-最大堆栈大小(KB)
 
#-cpu-最大cpu时间(分钟)
 
#-nproc-最大进程数
 
#-as-地址空间限制(KB)
 
#-max logins-此用户的最大登录次数
 
#-maxsyslogins-系统上的最大登录次数
 
#-priority-运行用户进程的优先级
 
#-locks-用户可以持有的最大文件锁数
 
#-sigpending-挂起信号的最大数目
 
#-msgqueue-POSIX消息队列使用的最大内存(字节)
 
#-nice-允许提升到值的最大nice优先级:[-20,19]
 
#-rtprio-最大实时优先级

cpu的亲和设置

cpu的亲和能够使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。

 相关命令

查看物理cpu个数

[root@localhost ~]# cat /proc/cpuinfo | grep "physical id" | sort|uniq | wc -l
1

查看cpu核心数

[root@localhost ~]#  cat /proc/cpuinfo|grep "cpu cores"|uniq 
cpu cores	: 3

 查看cpu使用率

[root@localhost ~]# top   回车后按1
 

查看逻辑cpu的个数(逻辑cpu=物理cpu*cpu核心数)

[root@localhost ~]# grep "siblings" /proc/cpuinfo|uniq
siblings	: 3

查看nginx使用cpu核心和对应的nginx进程号

[root@localhost ~]# ps -eo pid,args,psr |grep [n]ginx

具体设置

nginx运行进程个数一般设置CPU的核心数。#根据自己cpu核心数配置/这里也可以设置为auto

[root@lx~]# vi/usr/local/nginx1.10/conf/nginx.conf
worker_processes 4;
[root@lx~]# /usr/local/nginx1.10/sbin/nginx-s reload
[root@lx~]# ps -aux | grep nginx |grep -v grep
root 9834 0.0 0.0 47556 1948 ?     Ss 22:36 0:00 nginx: master processnginx
www 10135 0.0 0.0 50088 2004 ?       S   22:58 0:00 nginx: worker process
www 10136 0.0 0.0 50088 2004 ?       S   22:58 0:00 nginx: worker process
www 10137 0.0 0.0 50088 2004 ?       S   22:58 0:00 nginx: worker process
www 10138 0.0 0.0 50088 2004 ?       S   22:58 0:00 nginx: worker process

四核配置的话,我们就把nginx的进程数设为4

worker_processes 4;
worker_cpu_affinity 0001 0010 0100 1000

八核的话就设置为8

worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;

worker_processes最多开启8个,8个以上性能提升不会再提升了,而且稳定性变得更低,所以8个进程够用了。

为每个进程分配cpu,上例中将8个进程分配到8个cpu,当然可以写多个,或者将一个进程分配到多个cpu。

在nginx 1.9版本之后,就帮我们自动绑定了cpu;
worker_cpu_affinity auto;

事件处理模型优化

nginx的连接处理机制在于不同的操作系统会采用不同的I/O模型,Linux下,nginx使用epoll的I/O多路复用模型,在freebsd使用kqueue的IO多路复用模型,在solaris使用/dev/pool方式的IO多路复用模型,在windows使用的icop等等。要根据系统类型不同选择不同的事务处理模型,我们使用的是Centos,因此将nginx的事件处理模型调整为epoll模型。

在不指定事件处理模型时,nginx默认会自动的选择最佳的事件处理模型服务。

events {
    worker_connections  10240;    //
    use epoll;
}

设置work_connections 连接数

 worker_connections  10240;

keepalive timeout会话保持时间

keepalive_timeout  60;

GZIP压缩性能优化

gzip on;       #表示开启压缩功能
gzip_min_length  1k; #表示允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。默认值是0,表示不管页面多大都进行压缩,建议设置成大于1K。如果小于1K可能会越压越大
gzip_buffers     4 32k; #压缩缓存区大小
gzip_http_version 1.1; #压缩版本
gzip_comp_level 6; #压缩比率, 一般选择4-6,为了性能gzip_types text/css text/xml application/javascript;  #指定压缩的类型 gzip_vary on; #vary header支持

proxy超时设置

proxy_connect_timeout 90;
proxy_send_timeout  90;
proxy_read_timeout  4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k

高效传输模式

sendfile on; # 开启高效文件传输模式。
tcp_nopush on; #需要在sendfile开启模式才有效,防止网路阻塞,积极的减少网络报文段的数量。将响应头和正文的开始部分一起发送,而不一个接一个的发送。

通用配置优化

#将nginx进程设置为普通用户,为了安全考虑
user nginx; 
 
#当前启动的worker进程,官方建议是与系统核心数一致
worker_processes 2;
#方式一,就是自动分配绑定
worker_cpu_affinity auto;
 
#日志配置成warn
error_log /var/log/nginx/error.log warn; 
pid /var/run/nginx.pid;
 
#针对 nginx 句柄的文件限制
worker_rlimit_nofile 35535;
#事件模型
events {
    #使用epoll内核模型
    use epoll;
    #每一个进程可以处理多少个连接,如果是多核可以将连接数调高 worker_processes * 1024
    worker_connections 10240;
}
 
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
 
    charset utf-8;  #设置字符集
 
    #设置日志输出格式,根据自己的情况设置
    log_format  main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for" '
                      '"$args" "$request_uri"';
 
    access_log  /var/log/nginx/access.log  main;
 
    sendfile        on;   #对静态资源的处理比较有效
    #tcp_nopush     on;   #如果做静态资源服务器可以打开
    #tcp_nodeny     on;   #当nginx做动态的服务时可以选择打开
 
    keepalive_timeout  65; 
 
    ########
    #Gzip module
    gzip  on;    #文件压缩默认可以打开
    gzip_disable "MSIE [1-6]\."; #对于有些浏览器不能识别压缩,需要过滤如ie6
    gzip_http_version 1.1;
 
    include /etc/nginx/conf.d/*.conf;
}

注意:当需要对nginx进行优化时,我们可以通过两个方面对服务进行优化。即系统层面和服务层面。服务层面受限于系统层面的设置,而系统层面又受限于系统的配置。

ab接口压力测试工具

ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求。

[root@nginx-server ~]# yum install httpd-tools
[root@nginx-server ~]# ab -n 2000 -c 2 http://127.0.0.1/
-n 总的请求数
-c 并发数
-k 是否开启长连接

参数解释

-n:即requests,用于指定压力测试总共的执行次数
-c:即concurrency,用于指定的并发数
-t:即timelimit,等待响应的最大时间(单位:秒)
-b:即windowsize,TCP发送/接收的缓冲大小(单位:字节)
-p:即postfile,发送POST请求时需要上传的文件,此外还必须设置-T参数
-u:即putfile,发送PUT请求时需要上传的文件,此外还必须设置-T参数
-T:即content-type,用于设置Content-Type请求头信息,例如:application/x-www-form-urlencoded,默认值为text/plain
-v:即verbosity,指定打印帮助信息的冗余级别
-w:以HTML表格形式打印结果
-i:使用HEAD请求代替GET请求
-x:插入字符串作为table标签的属性
-y:插入字符串作为tr标签的属性
-z:插入字符串作为td标签的属性
-C:添加cookie信息,例如:"Apache=1234"(可以重复该参数选项以添加多个)
-H:添加任意的请求头,例如:"Accept-Encoding: gzip",请求头将会添加在现有的多个请求头之后(可以重复该参数选项以添加多个)
-A:添加一个基本的网络认证信息,用户名和密码之间用英文冒号隔开
-P:添加一个基本的代理认证信息,用户名和密码之间用英文冒号隔开
-X:指定使用的和端口号,例如:"126.10.10.3:88"
-V:打印版本号并退出
-k:使用HTTP的KeepAlive特性
-d:不显示百分比
-S:不显示预估和警告信息
-g:输出结果信息到gnuplot格式的文件中
-e:输出结果信息到CSV格式的文件中
-r:指定接收到错误信息时不退出程序
-H:显示用法信息,其实就是ab -help

示例:

[root@localhost ~]# ab -n 2000 -c 2 http://127.0.0.1/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
 
Benchmarking 127.0.0.1 (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests
 
 
Server Software:        nginx/1.20.2        #(服务器软件名称及版本信息)
Server Hostname:        127.0.0.1           #(服务器主机名)
Server Port:            80                  #(服务器端口)
 
Document Path:          /                    #(供测试的URL路径)
Document Length:        153 bytes            #(供测试的URL返回的文档大小)
 
Concurrency Level:      2                     #(并发数)
Time taken for tests:   0.163 seconds        #(压力测试消耗的总时间)
Complete requests:      2000                 #(发起请求的总次数)
Failed requests:        0                     #(失败的请求数)
Write errors:           0                     #(网络连接写入错误数)
Non-2xx responses:      2000                 
Total transferred:      606000 bytes           #(传输的总数据量)       
HTML transferred:       306000 bytes            #(HTML文档的总数据量)
Requests per second:    12274.98 [#/sec] (mean)  #(平均每秒的请求数) 这个是非常重要的参数数值,服务器的吞吐量 
Time per request:       0.163 [ms] (mean)       #(所有并发用户(这里是1000)都请求一次的平均时间)
Time per request:       0.081 [ms] (mean, across all concurrent requests)   #(单个用户请求一次的平均时间)
Transfer rate:          3632.15 [Kbytes/sec] received    #每秒获取的数据长度 (传输速率,单位:KB/s)
 
Connection Times (ms)                           #网络上消耗的时间的分解
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     0    0   0.4      0      12
Waiting:        0    0   0.3      0      12
Total:          0    0   0.4      0      12
 
Percentage of the requests served within a certain time (ms)    #网络消耗时间
  50%    347  ## 50%的请求在347ms内返回 
  66%    401  ## 60%的请求在401ms内返回 
  75%    431
  80%    516
  90%    600
  95%    846
  98%   1571
  99%   1593
  100%   1619 (longest request)

猜你喜欢

转载自blog.csdn.net/qq_50660509/article/details/129810828