【原】PHP项目性能优化之软件配置
in 技术 with 0 comment

【原】PHP项目性能优化之软件配置

in 技术 with 0 comment

授人以鱼不如授人以渔

前言

经过一段时间的忙碌,我们一直在致力于功能的全面以及技术的新颖,当然还有就是架构的华丽。但是就是好不好,牛不牛还必须得经历考验才行。所以笔者研究了下Jmeter,对ApiAdmin进行了“轰炸”,在此也记录下过程中的点滴,希望能帮助到大家,在今后的项目优化中不至于无从下手。

环境

第一次试水

本着对自己项目的绝对自信,我开始了第一次压测,结果果然不出意外,极低的吞吐量伴随着一堆的502。遇到这样的情况,我们应该如何去优化自己的项目呢?不要着急,冷静下来慢慢分析下,我们一定可以达到我们期望的结果。

请相信“我们的代码绝对不会有问题”

一个项目的优秀,不仅仅取决于代码,所以我们暂且认为我们的代码是没有问题的。项目又叫做工程,就拿ApiAdmin来讲,要想让ApiAdmin愉快的运行,我能想到的至少有以下几个必要因素:1、网络(带宽、域名解析);2、服务器(CPU,内存,硬盘);3、软件(Nginx、Redis、MySQL、PHP、MQ等);4、代码(算法);我们接下来就一一来寻找导致我们性能差的元凶,然后解决掉。因为我们本次主要调整的不是代码本身的性能,所以,我们在网站跟目录新建一个php文件,暂命名为t.php。

<?php
 echo "hello world";

我们之后的所有测试都将请求这个文件,以此来寻找非代码的性能杀手。

网络

带宽没啥好说的,有实力当然越高越好喽!这里我着重说下域名解析,由于目前的互联网发展方向是安全,所以https协议逐步成为主流,一切都是有代价的,安全的同时将牺牲掉性能,所以建议大家在做压测的时候使用http,这样才能反映出项目的真实情况,那么https解析慢不用解决么?当然要的,但是我们是解决不了的,所以就过了。

服务器

服务器的硬件资源是我们运行代码的基础,越是强大的机器,处理能力越强,相应的他能承载的压力也就越大。这里我只提一个要求物尽其用!如果你是16G的内存,但是由于你的配置,导致其中8G都是在空闲的,用不到的,这当然是不行的。这篇文章主要就是告诉大家如何去最大可能的发掘硬件性能。

软件

我们压测最常出现的问题就是502报错,502的意思就是错误的网关,它说明的信息就是nginx没有崩掉,因为nginx能正常返回502。由于我们使用的是最简单的代码,所以MySQL和Redis的问题也不会有,这里只能是一个地方出问题了-PHP。

nginx通过反向代理的方式,将PHP脚本都扔给php-fpm处理,如果这时候php-fpm坏了,没人帮助nginx处理php了,nginx当然就返回502了,这里大家注意几个PHP-FPM的配置。

/*
 * 将php-fpm监听方式由TCP的方式,变更为socket方式。
 * TCP方式效率较低,但是稳定性较好,平常推荐使用TCP方式,如果你有较高并发需求,请修改为socket方式。
 * 同时将socket监听文件请放在/dev/shm/运行效率会更高哦。
 * PS:这一切都是基于单机的基础上做的配置,如果是集群,请一定要注意,我们还是推荐使用TCP的方式来处理。
 */
listen = /dev/shm/fpm-cgi.sock;
/*
 * 这里的配置也是非常重要的,如出意外,很有可能出现502报错。
 * 因为常规情况我们运行nginx和php-fpm都会使用一个专有账号,如果不做设置,很有可能导致nginx无法读写socket文件。
 */
listen.owner = www
listen.group = www
listen.mode = 0666

/* 
 * 这个是一定需要关注的配置,这个是平衡CPU和内存使用的重要配置,理论情况下是越大越好。
 * 在我们并发请求服务器的时候,服务器其实也在并发处理各个请求,这个配置就是限制最大允许php-fpm并发数。
 * 这里值得注意的是,并发越大,那么所需要的内存也就越多,单个线程所承载的压力也就越低,相应的单个线程所使用的CPU也就越低。
 * 所以我们在调大这个配置参数的时候,一定要保证内存不能溢出,请多做压测,找一个适配的数值。
 */
pm.max_children = 80

PHP-FPM的配置所有的调整,我认为其主要目的就是尽可能的释放服务器的硬件性能,这也是我们本次优化的一个基础原则,也是项目优化的一个核心,由于我们的业务场景逐步变的复杂,涉及的关键节点越来越多,相关的配置我们还是要一次次调整的。

Nginx的配置我认为一般不用调整【单机情况】,因为一般我们安装的Nginx默认配置,就能够支撑起大量的并发,毕竟这是Nginx的特长之一嘛,所以建议大家不用太过纠结,这里我给大家一个我常用的nginx基础配置demo。

user www;
worker_processes  auto;

worker_rlimit_nofile 51200;

events {
    worker_connections  51200;
    multi_accept on;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    server_names_hash_bucket_size 128;
    client_header_buffer_size 32k;
    large_client_header_buffers 4 32k;
    client_max_body_size 50m;

    sendfile   on;
    tcp_nopush on;

    keepalive_timeout 60;

    tcp_nodelay on;

    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;

    gzip on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss;
    gzip_vary on;
    gzip_proxied   expired no-cache no-store private auth;
    gzip_disable   "MSIE [1-6]\.";

    #limit_conn_zone $binary_remote_addr zone=perip:10m;
    ##If enable limit_conn_zone,add "limit_conn perip 10;" to server section.

    server_tokens off;
    #access_log off;

    include vhost/*.conf;
}
Comments are closed.