189 8069 5689

如何进行nginx+php的性能优化

本篇文章给大家分享的是有关如何进行nginx+php 的性能优化,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

成都创新互联是一家以重庆网站建设、网页设计、品牌设计、软件运维、成都网站推广、小程序App开发等移动开发为一体互联网公司。已累计为成都报废汽车回收等众行业中小客户提供优质的互联网建站和软件开发服务。

准备工作

  • 一台ECS服务器

  • 手动编译nginx+php

  • 修改index.php ,输出 ‘hello world’

  • 用ab工具,ab -c 100 -n 50000 ,连续5次,记录压测的qps平均值。

  • 想办法去优化,调整各种参数。每次调整一个参数有发现QPS提高,那就记录下来,并思考qps瓶颈是在哪

Nginx 一些基本配置的描述

 user administrator administrators;  #配置用户或者组,默认为nobody nobody。
 worker_processes 2;  #允许生成的进程数,默认为1
 pid /nginx/pid/nginx.pid;   #指定nginx进程运行文件存放地址
 error_log log/error.log debug;  #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
 events { accept_mutex on;   #设置网路连接序列化,防止惊群现象发生,默认为on multi_accept on;  #设置一个进程是否同时接受多个网络连接,默认为off #use epoll;      #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport worker_connections  1024;    #最大连接数,默认为512
 }
 http { include       mime.types;   #文件扩展名与文件类型映射表 default_type  application/octet-stream; #默认文件类型,默认为text/plain #access_log off; #取消服务日志     log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式 access_log log/access.log myFormat;  #combined为日志格式的默认值 sendfile on;   #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。 sendfile_max_chunk 100k;  #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。 keepalive_timeout 65;  #连接超时时间,默认为75s,可以在http,server,location块。
 upstream mysvr {   
       server 127.0.0.1:7878;   server 192.168.10.121:3333 backup;  #热备 } error_page 404 https://www.baidu.com; #错误页 server { keepalive_requests 120; #单连接请求上限次数。 listen       4545;   #监听端口 server_name  127.0.0.1;   #监听地址        location  ~^.+$ {       #请求的url过滤,正则匹配,~为区分大小写,~为不区分大小写。#root path;  #根目录#index vv.txt;  #设置默认页proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表deny 127.0.0.1;  #拒绝的ipallow 172.18.5.54; #允许的ip            } 
     }}

接下来我们开始吧

ECS配置
CPU: 1核
内存: 1 GiB
操作系统: CentOS 7 64位
当前使用带宽: 1Mbps

在高并发的情况下,内核会认为系统受到了SYN flood攻击,会发送cookies(possible SYN flooding on port 80. Sending cookies),这样会减慢影响请求的速度,所以在应用服务器上设置下这个参数为0禁用系统保护就可以进行大并发测试了:

 $ vim /etc/sysctl.conf 
 $ net.ipv4.tcp_syncookies = 0
 $ sysctl -p
 $ net.ipv4.tcp_syncookies = 0

net.ipv4.tcp_syncookies = 0  #此参数是为了防止洪水攻击的,但对于大并发系统,要禁用此设置
net.ipv4.tcp_max_syn_backlog #参数决定了SYN_RECV状态队列的数量,一般默认值为512或者1024,即超过这个数量,系统将不再接受新的TCP连接请求,一定程度上可以防止系统资源耗尽。可根据情况增加该值以接受更多的连接请求。
net.ipv4.tcp_tw_recycle #参数决定是否加速TIME_WAIT的sockets的回收,默认为0。
net.ipv4.tcp_tw_reuse #参数决定是否可将TIME_WAIT状态的sockets用于新的TCP连接,默认为0。
net.ipv4.tcp_max_tw_buckets #参数决定TIME_WAIT状态的sockets总数量,可根据连接数和系统资源需要进行设置

默认编译测试,无修改:

ab -c 100 -n 50000 http://127.0.0.1/index.php
1、 7111 2、7233 3、7240 4、7187 5、7197 平均:7194

修改

worker_processes 1 => auto

worker_processes :工作进程数,调整一般为auto或者跟cpu核心一样的数量。

一般一个进程足够了,你可以把连接数设得很大。(worker_processes: 1,worker_connections: 10,000)
如果有SSL、gzip这些比较消耗CPU的工作,而且是多核CPU的话,可以设为和CPU的数量一样。(worker_processes: CPU核心数)
或者要处理很多很多的小文件,而且文件总大小比内存大很多的时候,也可以把进程数增加,以充分利用IO带宽(主要似乎是IO操作有block)

1、 7242 2、7228 3、7275 4、7234 5、7231 平均:7242

worker_connections 1020 => 65535

单个进程允许的客户端最大连接数,一般来说,连接数可以设置和端口数一样。

1、 7212 2、7236 3、7223 4、7260 5、7230 平均 7232

worker_rlimit_nofile 65535

worker进程最大打开文件数,一般可以优化设置成和端口数一样

1、 7243 2、7236 3、7146 4、7243 5、7196 平均 7212.8

use epoll;

使用epoll的I/O模型,事件处理模型优化。

1、7265 2、7196 3、7227 4、7216 5、7253 平均 7231

multi_accept ON

multi_accept指令使得NGINX worker能够在获得新连接的通知时尽可能多的接受连接。 此指令的作用是立即接受所有连接放到监听队列中。 如果指令被禁用,worker进程将逐个接受连接。
1、 7273 2、7281 3、7308 4、7299 5、7290 平均 7290

accept_mutex ON

由于我们在NGINX中配置了多个workers,因此我们还应配置影响worker的相关指令。 events区域下accept_mutex参数将使每个可用的worker进程逐个接受新连接。设置网路连接序列化,防止惊群现象发生,默认为on。
服务器是1核,所以影响不大
1、7268 2、7295 3、7308 4、7274 5、7261 平均 7281

tcp_nopush On

TCP_CORK作为Nagle算法的替代方案,Linux提供了TCP_CORK选项。 该选项告诉TCP堆栈附加数据包,并在它们已满或当应用程序通过显式删除TCP_CORK指示发送数据包时发送它们。 这使得发送的数据分组是最优量,并且因此提高了网络的效率。
NGINX提供了tcp_nopush指令,在连接套接字时启用TCP_CORK。 该指令可用于http,server和location区块:
http{
     tcp_nopush on;
}
1、7309 2、7321 3、7292 4、7308 5、7322 平均 7310

tcp_nodelay on

TCP/IP网络存在“小包”问题,其中单字符消息可能在高负载网络上导致网络拥塞。 例如分组大小为41字节,其中40字节用于TCP报头,只有1字节是有用信息。 这些小包占用了大约4000%的巨大开销并且使得网络饱和
ohn Nagle通过不立即发送小包来解决问题(Nagle的算法)。 所有这样的分组被收集一定量的时间,然后作为单个分组一次发送。 这改进了底层网络的的效率。 因此,典型的TCP/IP协议栈在将数据包发送到客户端之前需要等待200毫秒。
在打开套接字时可以使用TCP_NODELAY选项来禁用Nagle的缓冲算法,并在数据可用时立即发送。 NGINX提供了tcp_nodelay指令来启用此选项。 该指令可用于http,server和location区块:
http{
     tcp_nodelay on;
}

1、 7326 2、7316 3、7334 4、7274 5、7290 平均 7308

worker_priority -5

指明worker进程的nice值
Linux系统中,优先级高的进程会占用更多的系统资源,这里配置的是进程的静态优先级,取值范围-20到+19,-20级别最高。因此可以把这个值设置小一点,但不建议比内核进程的值低(通常为-5)

测试中 0到-5的性能提升明显 0可达到8000均值
1、 7982 2、8023 3、7932 4、7911 5、8052 平均 7980

php-fpm参数调优

pm = dynamic; 
表示使用哪种进程数量管理方式
    dynamic表示php-fpm进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理,保证多余的进程数不多于pm.max_spare_servers
    static表示php-fpm进程数是静态的, 进程数自始至终都是pm.max_children指定的数量,不再增加或减少
  1.pm.start_servers = 15; 动态方式下的起始php-fpm进程数量
  2.pm.min_spare_servers = 5; 动态方式下的最小php-fpm进程数量
3.pm.max_spare_servers = 25; 动态方式下的最大php-fpm进程数量
4.pm.max_requests = 5000
设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 ’0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0. 这段配置的意思是,当一个 PHP-CGI 进程处理的请求数累积到 5000 个后,自动重启该进程。
7934 2 、8107 3 、8013 4、8039 5、7990 均值 8016

opcache

opcache 绝对是优化的利器,Opcache是字节码缓存,也就是PHP在被编译的时候,首先会把php代码转换为字节码,字节码然后被执行。
php文件第二次执行时,同样还是会重新转换为字节码,但是很多时候,文件内容几乎是一样的,比如静态HTML文件,生成后内容许久都不会改变,用户访问请求直接由服务器读取响应给客户端浏览器。都不用经过PHP进行解析构建了。
内存中的字节码数据,可以直接缓存进行二次编译。这样程序就会快一些,cpu的消耗也少了。

结论

php-fpm 采用 prefork的方式 (listen同一个地址,然后fork出若干子进程),fast-cgi管理器实现的是多进程模型。

但是在php运行时,每一个进程只能处理一个请求,实际上,运行时是单进程,单线程的。

php-fpm一个线程是阻塞模型,必须等待该客户端请求php服务端返回数据,下一个nginx发过来的请求才能被受理,这个时候FPM就需要增多进程去应付并发,更高的qps 需要更多的进程处理,当处理请求的时候发生了时间较长阻塞,导致进程内存无法释放,后续请求没有足够的子进程去处理,更多的瓶颈在于 PHP-FPM 大量子进程的处理和消耗内存上面。

以上就是如何进行nginx+php 的性能优化,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注创新互联行业资讯频道。


文章标题:如何进行nginx+php的性能优化
本文地址:http://cdxtjz.com/article/gcooep.html

其他资讯