PHP-FPM配置的优化

php-fpm默认安装后以下三个参数都是关闭的:

#表示在 emergency_restart_interval 所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果

#超过 emergency_restart_threshold 个php-fpm就会优雅重启。这两个选项一般保持默认值。

emergency_restart_threshold = 10
emergency_restart_interval = 1m

#设置子进程接受主进程复用信号的超时时间. 可用单位: s(秒), m(分), h(小时), 或者 d(天) 默认单位: s(秒). 默认值: 0.

process_control_timeout = 0

出于优化的目的,我们把它们打开

emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 10s

有以下优点

在1分钟内,出现 SIGSEGV 或者 SIGBUS 错误的 PHP-CGI 进程数超到10个时,PHP-FPM 就会优雅的自动重启。

SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。

php-fpm 占用CPU过高,100%的解决方法

话说最近配置的LNMP还算稳定,正在暗自窃喜,但是从昨晚开始,就发现服务器的CPU占用过高,甚至到了100%。我的内存是1G的,正常情况下占用率应该在5%以下,最多不超10%。

阿里云最近的监控显示:

未分类

使用top命令查看,发现 php-fpm 占用内存过高,非常不正常:

未分类

我按照《Nginx使用的php-fpm的两种进程管理方式及优化》这篇文章,配置 php-fpm 进程数如下:

未分类

重启 php-fpm 后,还是没有彻底解决问题,依旧会出现占用 99以上,不知道哪位朋友知道如何分析和解决呢?小弟求助了!

后续进展

昨天(3月29日)找 @容哥 指导检查,后来发现是 eAccelerator 组件不知什么原因占用 CPU 过高,打开 php.ini

vi /usr/local/php/etc/php.ini

删除 eAccelerator 的配置信息,重启 lnmp

/root/lnmp restart

但还是没有彻底解决问题,几个小时后,我又重启了 lnmp ,居然发现,似乎已经越来越平稳啦。

可能用到的命令:

top                //查看CPU、内存使用信息,查看哪个进程占用CPU高以及它的PID

ll /proc/PID号/fd/             // 通过PID找到哪个文件操作的进程,进而知道问题所在

Nginx使用的php-fpm的两种进程管理方式及优化

这篇文章主要介绍了Nginx使用的php-fpm的两种进程管理方式及优化,需要的朋友可以参考下
PS:前段时间配置php-fpm的时候,无意中发现原来它还有两种进程管理方式。与Apache类似,它的进程数也是可以根据设置分为动态和静态的。

php-fpm目前主要又两个分支,分别对应于php-5.2.x的版本和php-5.3.x的版本。在5.2.x的版本中,php-fpm.conf使用的是xml格式,而在新的5.3.x版本中,则是和php.ini一样的配置风格。
在5.2.x版本中,php-fpm.conf中对于进程管理号称是有两种风格,一种是静态(static)的,一种是类似于apache风格(apache-like)的。

代码如下:

Process manager settings
<value name=”pm”>
Sets style of controling worker process count.
Valid values are 'static' and ‘apache-like'
<value name=”style”>static</value>

按照文档的说明,如果pm的style采用apache-like,启动的进程数应该是和StartServers指定的一样。不过经过数次的尝试,会发现,实际上在这里将pm的style配置成apache-like没有起任何作用。也就是说,这里的apache-like并没有被实现。
不过,在最新的5.3.x的配套php-fpm中,apache风格的进程管理已经被实现了。

代码如下:

; Choose how the process manager will control the number of child processes.
; Possible Values:
; static - a fixed number (pm.max_children) of child processes;
; dynamic - the number of child processes are set dynamically based on the
; following directives:
; pm.max_children - the maximum number of children that can
; be alive at the same time.
; pm.start_servers - the number of children created on startup.
; pm.min_spare_servers - the minimum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is less than this
; number then some children will be created.
; pm.max_spare_servers - the maximum number of children in 'idle'
; state (waiting to process). If the number
; of 'idle' processes is greater than this
; number then some children will be killed.
; Note: This value is mandatory.
;pm = dynamic
pm = static

由上面一段文字可知,对于进程的管理存在两种风格——static和dynamic。和之前的版本的进程管理其实还是一样的,只是将apache-like改成了dynamic,这样更容易理解。

如果设置成static,php-fpm进程数自始至终都是pm.max_children指定的数量,不再增加或减少。
如果设置成dynamic,则php-fpm进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理,保证多余的进程数不多于pm.max_spare_servers。

这两种不同的进程管理方式,可以根据服务器的实际需求来进行调整。

这里先说一下涉及到这个的几个参数,他们分别是pm、pm.max_children、pm.start_servers、pm.min_spare_servers和pm.max_spare_servers。
pm表示使用那种方式,有两个值可以选择,就是static(静态)或者dynamic(动态)。在更老一些的版本中,dynamic被称作apache-like。这个要注意看配置文件的说明。

下面4个参数的意思分别为:

  • pm.max_children:静态方式下开启的php-fpm进程数量。
  • pm.start_servers:动态方式下的起始php-fpm进程数量。
  • pm.min_spare_servers:动态方式下的最小php-fpm进程数量。
  • pm.max_spare_servers:动态方式下的最大php-fpm进程数量。

如果dm设置为static,那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程。
如果dm设置为dynamic,那么pm.max_children参数失效,后面3个参数生效。系统会在php-fpm运行开始的时候启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数。

那么,对于我们的服务器,选择哪种执行方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。
对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。
对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

php-fpm 搭建

php-fpm 即 php-Fastcgi Process Manager。
php-fpm 是 FastCGI 的实现,并提供了进程管理的功能。
进程包含 master 进程和 worker 进程两种进程。
master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个 (具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。

配置 nginx 和 php-fpm 交互

  • 配置 nginx 文件
  location ~* .php$ {
    root           html;
    fastcgi_pass   127.0.0.1:9000;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
  }

当请求的 url 能匹配以.php 结尾时,将反向代理给 php-fpm 处理动态信息。
root 是配置 php 程序放置的根目录。
fastcgi_pass 指令表示将该 url 请求代理至 nginx fastcgi 进程监听的 IP 地址和端口。
fastcgiparam 表示读取的是 $document_root(网站根目录)下的.php 文件;如果没有配置这一配置项,nginx 不会访问根目录的 php。

fastcgi_params 文件中含有各个 nginx 常量的定义,默认情况 SCRIPT_FILENAME=$fastcgi_script_name

Apache、Nginx、php-fpm为PHP设置、添加$_SERVER服务器环境变量

在PHP开发中为了区分线上生产环境还是本地开发环境,

如果我们能通过判断$_SERVER['RUNTIME_ENVIROMENT']'DEV'还是'PRO'来区分该多好,

可惜的是$_SERVER数组里面根本没有RUNTIME_ENVIROMENT这个元素。

一、通过nginx的fastcgi_param来设置

在nginx配置文件中,可以在nginx总体的配置文件nginx.conf中,也可以在单独的网站配置环境中进行设置,如:www.regskynet.com.conf

在配置环境server段location中添加相应的配置信息:

    location ~ .php$ {
        limit_conn conn_zone 15;
        limit_req zone=req_zone burst=25 nodelay;
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        root           $root;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_param  RUNTIME_ENVIROMENT 'PRO';
    }

然后重启重启nginx

service nginx reload

二、通过php主配置文件php-fpm.conf来设置

这个设置必须放在主配置文件php-fpm.conf里,不能放到include指令设置的子配置文件里,否则会报错:「Array are not allowed in the global section」

我的php-fpm.conf位置在/etc/php-fpm.conf

直接在配置文件中添加:

env[RUNTIME_ENVIROMENT] = 'PRO'

添加后重启php-fpm

service php-fpm reload

通过上面2种方式添加$_SERVER变量值后,我们就可以直接在php文件中通过$_SERVER来获取相应的变量值了。

不过据说配置信息通过nginxfastcgi_param来设置的话,当nginx和php交互时,会带来大量的数据传输。

三、通过Apache设置环境变量

SetEnv 变量名 变量值

<VirtualHost *:80>
    ServerAdmin ...
    DocumentRoot ...
    ServerName www.regskynet.com
    ErrorLog ...
    CustomLog ...
    SetEnv RUNTIME_ENVIROMENT PRO
    <Directory "...">
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

nginx+php-fpm故障排查

小明初到一家公司做运维的工作,刚来的第一天就开始部署LNMP(Linux+Nginx+MySQL+PHP)环境,结果出现了问题。

他来向我请教,具体问题现象、原因和解决思路如下:

问题一
nginx进程CPU和内存不均衡,某个进程占用资源特别高,如何解决?
回答:我让小明绑定下CPU的亲缘性(设置nginx配置worker_cpu_affinity项为auto,auto这个特殊值(1.9.10版本)允许自动绑定工作进程到可用的CPU上。),绑定后CPU和内存使用就均衡了。

问题二
小明又问close系统调用消耗很高怎么解决?

回答:且听我娓娓道来,继续看下文。

strace−cpstrace−cp(pgrep -n nginx)

未分类

$ top

未分类

系统32c的,top查看负载去到75.14,

查看过nginx和php-fpm的

错误日志也没有什么发现。

strace 跟踪close的系统调用,

都是以下的信息:

strace−T−ttpstrace−T−ttp(pgrep -n nginx) 2&>1 |grep -B 10 close > ./close.log

未分类

$ lsof | more

未分类

遂怀疑是连接创建关闭消耗了太多的资源,便让小明加了台机器专门跑nginx,
前端挂了个nginx用长连接跟后端的nginx连接,接了个nginx之后负载果然就下来了。

未分类

前端未挂nginx压测ab压测结果:

未分类

前端挂了nginx压测ab压测结果:

未分类

tps基本没变第一个Time per,requset快了87.52%。
接着继续排查tps上不去的原因,继续strace后端的nginx。

strace−cpstrace−cp(pgrep -n nginx)

未分类

发现现在是wrtiev占用高了,strace 跟踪close的系统调用,
发现很多以下的输出:

connect(26, {sa_family=AF_INET, 
sin_port=htons(9000), 
sin_addr=inet_addr("127.0.0.1")},
16) = -1 EINPROGRESS
(Operation now in progress)

问题应该不是在nginx上,
应该是在php-fpm上了。
继续

strace−cpstrace−cp(pgrep -n php-fpm)

显示下图所示:

未分类

access cpu时间消耗最多那就先
排查access
系统调用:

strace−T−ttpstrace−T−ttp(pgrep -n php-fpm) 2&>1 |
grep -B 10 access >
./access.log

未分类

php-fpm进程频繁的去读取文件,整个操
作下来花费4ms的时间。

然后排查recvfrom:

strace−T−ttpstrace−T−ttp(pgrep -n 
php-fpm) 2&>1 |
grep -B 10 recvfrom > 
./recvfrom.log

未分类

频繁的去访问10.0.0.156的6379,端口,明显就是访问redis读取数据的过程,
整个过程花费12ms。
让小明把上面两个strace信息发给开发,第一个得到回复是老版本的流程,
新版本改了,但还是有些判断没有处理。
第二个问题让开发使用redis连接池,无需频繁创建连接读取数据,
频繁创建连接开销很大的。

总 结
当遇上性能问题时,排查日志无法解决时,使用strace工具来查看一下系统调用,看时间到底消耗在哪里了,可以轻松的找到问题所在。

为所有PHP-FPM容器构建单独的Nginx Docker镜像

最近,原文作者一直在使用Docker容器来开发PHP微服务套件。一个问题是PHP应用已经搭建,可以和PHP-FPM和Nginx(取代了简单的Apche/PHP环境)一起工作,因此每个PHP微服务需要两个容器(以及两个Docker镜像):一个PHP-FPM容器和一个NGinx容器。
这个应用运行了6个以上的服务,如果做个乘法,在开发和生产之间会有约30个容器。作者决定构建一个单独的NGinx Docker镜像,它可以使用PHP-FPM的主机名作为环境变量并运行单独的配置文件,而没有为每个容器构建单独的NGinx镜像。

未分类

在本文中,原文作者简要说明从上图中的方法1到方法2的转换,最后采用的方案中采用了一种新的定制Docker镜像。该镜像的代码是开源的,如果读者碰到类似问题,可以随时签出该部分代码。

为什么用 NGinx?

NGinx和PHP-FPM配合使用能使PHP应用的性能更好,但不好的是和PHP Apache镜像不同,PHP-FPM Docker镜像缺省并没有和NGinx进行绑定。如果需要通过NGinx容器和PHP-FPM连接,需要在NGind配置里为该后端增加DNS记录。比如,如果名为php-fpm-api的PHP-FPM容器正在运行,NGinx配置文件应该包含下面部分:

    location ~ .php$ {
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        # This line passes requests through to the PHP-FPM container
        fastcgi_pass php-fpm-api:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

如果只服务于单独的NGinx容器,NGinx配置中容器名字写死还可以接受,但如上所述,需要允许多个NGinx容器,每个对应于一个PHP服务。创建一个新的NGinx镜像(以后需要进行维护和升级)会有些痛苦,即使管理一批不同的数据卷,仅仅改变变量名看起来也有很多工作。

第一种方案: 使用Docker文档中的方法

最初,作者认为这会很简单。Docker文档中有少许的几个章节讨论如何使用envsubst来完成该工作,但不幸的是,在其NGinx配置文件中,这种方法不奏效。

vhosts.conf

server {
    listen 80;
    index index.php index.html;
    root /var/www/public;
    client_max_body_size 32M;
    location / {
        try_files $uri /index.php?$args;
    }
    location ~ .php$ {
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        fastcgi_pass ${NGINX_HOST}:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

该vhosts.conf文件使用了NGinx内置变量,因此当依照文档运行Docker命令(/bin/bash -c “envsubst < /etc/nginx/conf.d/mysite.template > /etc/nginx/conf.d/default.conf && nginx -g ‘daemon off;’”)时,得到错误提示$uri和$fastcgi_script_name没有定义。这些变量通常通过NGinx传入,因此不能简单的识别出他们是什么并传给自身,而且这使容器的动态性变差。

用另一个Docker镜像来救急,差点成功

接下来,作者开始研究不同的NGinx镜像。找到的两个,但它们都在随后的几年中都没有任何更新。作者开始使用martin/nginx,试图找到可以工作的原型。
Martin镜像和其它镜像有点不一样,因为它要求特定的文件夹结构。在root下增加Dockerfile:

FROM martin/nginx

接下来,我添加了一个app/空目录和conf/目录,conf/目录下只有一个文件vhosts.conf:

server {
    listen 80;
    index index.php index.html;
    root /var/www/public;
    client_max_body_size 32M;
    location / {
        try_files $uri /index.php?$args;
    }
    location ~ .php$ {
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        fastcgi_pass $ENV{"NGINX_HOST"}:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

这个文件和之前的配置文件几乎一样,除了有一行的改动:

fastcgi_pass $ENV{“NGINX_HOST”}:9000;。现在想要启动带命名为php-fpm-api的PHP容器的NGinx容器,就可以构建一个新的镜像,让它在以下环境变量下运行:

docker build -t shiphp/nginx-env:test .
docker run -it --rm -e NGINX_HOST=php-fpm-api shiphp/nginx-env:test

它可以正常工作了。但是,这种方法有两个困扰的地方:
1. 正在使用的基础镜像已经有两年了。这会引入安全和性能风险。
2. 有个空的/app目录看起来并不必需,因为文件会被存储在一个不同的目录中。

最终解决方案

作者认为作为定制解决方案,从Martin镜像开始比较好,因此给项目建了分叉,创建了新的NGinx基础镜像并修复了上述两个问题。现在,如果要在NGinx容器中允许动态命名的后端,可以参照:

# 从Docker Hub得到最新版本
docker pull shiphp/nginx-env:latest
# 运行名为"php-fpm-api"的PHP容器 
docker run --name php-fpm-api -v $(pwd):/var/www php:fpm
# 允许链接到PHP-FPM容器的NGinx容器
docker run --link php-fpm-api -e NGINX_HOST=php-fpm-api shiphp/nginx-env

如果想增加自己的文件或NGinx配置文件,来定制镜像,用Dockerfile来扩展它就可以:

FROM shiphp/nginx-env

ONBUILD ADD <PATH_TO_YOUR_CONFIGS> /etc/nginx/conf.d/

...

现在所有的PHP-FPM容器都使用了它们自己的Docker镜像实例,这样在升级NGinx,改变权限或做某些调整时,就变得非常轻松了。 所有的代码都在Github上,如果读者看到任何问题或有改进建议,可以直接创建一个问题单。如果有疑问或任何Docker相关的,可以在Twitter上找到我继续探讨。

查看英文原文:https://www.shiphp.com/blog/2018/nginx-php-fpm-with-env

配置一个nginx+php-fpm的web服务器

一、基本信息

  • 系统(L):CentOS 6.9 #下载地址:http://mirrors.sohu.com
  • Web服务器(N):NGINX 1.14.0 #下载地址:http://nginx.org/en/download.html
  • 数据库服务器(M):MySQL 5.6.40 #下载地址:https://dev.mysql.com/downloads/mysql
  • PHP-FPM服务器(P):php-5.6.8.tar.gz #下载地址:http://mirrors.sohu.com/php/
  • OPENSSL:openssl-1.0.2o.tar.gz #下载地址:https://www.openssl.org/source/

指定服务安装的通用位置

mkdir /usr/local/services
SERVICE_PATH=/usr/local/services

创建服务运行的账户

useradd -r -M -s /sbin/nologin www

安装所需依赖包

yum -y install pcre pcre-devel 
gperftools gcc zlib-devel 
libxml2 libxml2-devel 
bzip2 bzip2-devel 
curl curl-devel 
libjpeg-devel libjpeg 
libpng-devel libpng 
freetype freetype-devel 
libmcrypt libmcrypt-devel 
openssl-devel

二、软件安装配置

1、NGINX+OPENSSL安装

下载解压NGINX+OPENSSL

NGINX_URL="http://nginx.org/download/nginx-1.14.0.tar.gz"
OPENSSL_URL="https://www.openssl.org/source/openssl-1.1.0h.tar.gz"

wget -P ${SERVICE_PATH} ${NGINX_URL} && tar -zxvf ${SERVICE_PATH}/nginx*.tar.gz -C ${SERVICE_PATH}
wget -P ${SERVICE_PATH} ${OPENSSL_URL} && tar -zxvf ${SERVICE_PATH}/openssl*.gz -C ${SERVICE_PATH}

编译安装NGINX

cd ${SERVICE_PATH}/nginx-*;./configure 
--prefix=${SERVICE_PATH}/nginx 
--user=www --group=www 
--with-http_stub_status_module 
--with-http_ssl_module 
--with-http_flv_module 
--with-pcre 
--with-http_gzip_static_module 
--with-openssl=${SERVICE_PATH}/openssl* 
--with-http_realip_module 
--with-google_perftools_module 
--without-select_module 
--without-mail_pop3_module 
--without-mail_imap_module 
--without-mail_smtp_module 
--without-poll_module 
--without-http_autoindex_module 
--without-http_geo_module 
--without-http_uwsgi_module 
--without-http_scgi_module 
--without-http_memcached_module 
--with-cc-opt='-O2' && cd ${SERVICE_PATH}/nginx-*;make && make install

NGINX+OPENSSL安装完成后的清理与其他配置

ln -sv ${SERVICE_PATH}/nginx /usr/local/
rm -rf ${SERVICE_PATH}/nginx/conf/*.default
cd ${SERVICE_PATH} ; rm -rf nginx*.tar.gz openssl*.tar.gz

写入主配置文件nginx.conf(配置已优化)

cat << EOF >/usr/local/nginx/conf/nginx.conf
user www;
worker_processes WORKERNUMBER;
worker_cpu_affinity auto;
worker_rlimit_nofile 655350;

error_log /var/log/nginx_error.log;
pid /tmp/nginx.pid;

google_perftools_profiles /tmp/tcmalloc;

events {
use epoll;
worker_connections 655350;
multi_accept on;
}

http {
charset utf-8;
include mime.types;
default_type text/html;

log_format main '"$remote_addr" - [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" '
'"$sent_http_server_name $upstream_response_time" '
'$request_time '
'$args';


sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 120;
client_body_buffer_size 512k;
client_header_buffer_size 64k;
large_client_header_buffers 4 32k;
client_max_body_size 300M;
client_header_timeout 15s;
client_body_timeout 50s;
open_file_cache max=102400 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
server_names_hash_max_size 2048;
server_names_hash_bucket_size 256;
server_tokens off;
gzip on;
gzip_proxied any;
gzip_min_length 1024;
gzip_buffers 4 8k;
gzip_comp_level 9;
gzip_disable "MSIE [1-6].";
gzip_types application/json test/html text/plain text/css application/font-woff application/pdf application/octet-stream application/x-javascript application/javascript application/xml text/javascript;
fastcgi_cache_path /dev/shm/ levels=1:2 keys_zone=fastcgicache:512m inactive=10m max_size=3g;
fastcgi_cache_lock on;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
fastcgi_send_timeout 300;
fastcgi_connect_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 256k;
fastcgi_buffers 4 128k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;


include vhost/*.conf;
}
EOF

NGINX worker进程数配置,指定为逻辑CPU数量的2倍

THREAD=`expr $(grep process /proc/cpuinfo |wc -l) * 2`
sed -i s"/WORKERNUMBER/$THREAD/" ${SERVICE_PATH}/nginx/conf/nginx.conf

2、PHP-FPM安装

下载并解压PHP-FPM软件

FPM_URL="http://mirrors.sohu.com/php/php-5.6.8.tar.gz"
wget -P ${SERVICE_PATH} ${FPM_URL} && tar -zxvf ${SERVICE_PATH}/php*.tar.gz -C ${SERVICE_PATH}

编译安装PHP-FPM

cd ${SERVICE_PATH}/php-*;./configure 
--prefix=${SERVICE_PATH}/php 
--with-gd 
--with-mcrypt 
--with-mysql=mysqlnd 
--with-mysqli=mysqlnd 
--with-pdo-mysql=mysqlnd 
--enable-maintainer-zts 
--enable-ftp 
--enable-zip 
--with-bz2 
-with-iconv-dir 
--with-freetype-dir 
--with-jpeg-dir 
--with-png-dir 
--with-config-file-path=${SERVICE_PATH}/php 
--enable-mbstring 
--enable-fpm 
--with-fpm-user=www 
--with-fpm-group=www 
--disable-debug 
--enable-opcache 
--enable-soap 
--with-zlib 
--with-libxml-dir=/usr 
--enable-xml 
--disable-rpath 
--enable-bcmath 
--enable-shmop 
--enable-sysvsem 
--enable-inline-optimization 
--with-curl 
--enable-mbregex 
--enable-gd-native-ttf 
--with-openssl 
--with-mhash 
--enable-pcntl 
--enable-sockets 
--with-xmlrpc 
--with-pear 
--with-gettext 
--disable-fileinfo && cd ${SERVICE_PATH}/php-*;make && make install

若FPM程序有插件需求,如mongo或redis连接插件,则可通过pecl安装php相关插件

${SERVICE_PATH}/php/bin/pecl install mongo || exit

${SERVICE_PATH}/php/bin/pecl install redis || exit

安装完成后的配置清理

ln -sv ${SERVICE_PATH}/php /usr/local/

php.ini配置文件写入(配置已优化)

cat << EOF >${SERVICE_PATH}/php/php.ini 
[PHP]
engine = On
short_open_tag = Off
asp_tags = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = 17
disable_functions = shell_exec,phpinfo,exec
disable_classes =
zend.enable_gc = On
expose_php = Off
max_execution_time = 60
max_input_time = 60
memory_limit = 128M
error_reporting = E_WARING & ERROR
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 2048
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
html_errors = Off
error_log = /var/log/php_errors.log
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 8M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
cgi.fix_pathinfo=0
file_uploads = On
upload_max_filesize = 2M
max_file_uploads = 20
allow_url_fopen = Off
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
[filter]
[iconv]
[intl]
[sqlite]
[sqlite3]
[Pcre]
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
SMTP = localhost
smtp_port = 25
mail.add_x_header = On
[SQL]
sql.safe_mode = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[OCI8]
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.save_path = "/tmp"
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off
[Assertion]
[COM]
[mbstring]
[gd]
gd.jpeg_ignore_warning = 0
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[mcrypt]
[dba]
[opcache]
opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=4000
opcache.validate_timestamps=1
opcache.revalidate_freq=30
opcache.fast_shutdown=1
opcache.enable_file_override=1
[curl]
[openssl]
extension_dir='${SERVICE_PATH}/php/lib/php/extensions/'
;extension=mongo.so
;extension=redis.so
EOF

php-fpm.conf配置文件写入(配置已优化)

cat << EOF >${SERVICE_PATH}/php/etc/php-fpm.conf
[global]
error_log = /var/log/php-fpm-error.log
log_level = warning
process_control_timeout = 10
rlimit_files = 655350
events.mechanism = epoll
[www]
user = www
group = www
listen = /dev/shm/php-fpm.sock
listen.backlog = 2048
listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 200
pm.start_servers = 105
pm.min_spare_servers = 10
pm.max_spare_servers = 200
pm.process_idle_timeout = 10s;
pm.max_requests = 1000
pm.status_path = /fpmstatus
ping.path = /ping
ping.response = pong
slowlog = /var/log/php-slow-$pool.log
request_slowlog_timeout = 10
request_terminate_timeout = 0
rlimit_files = 655350
security.limit_extensions = .php
EOF

三、基于以上配置PHP网站

mkdir /usr/local/nginx/conf/vhost
cat << EOF > /usr/local/nginx/conf/vhost/erbiao.ex.com.conf
server
{
listen 80 backlog=1024;
server_name erbiao.ex.com;
index index.php index.html ;
root /www/web/;
access_log off;
add_header Server-Name WEBerbiaoEX;

location ~ .php {
fastcgi_pass unix:/dev/shm/php-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;


location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}

location ~ .*.(js|css)?$
{
expires 12h;
}

}

}
EOF

若在同一服务器运行nginx和php-fpm,并发量不超过1000,选择unix socket,如此可避免一些检查操作(路由等),因此更快,更轻。若是高并发业务,则选择使用更可靠的tcp socket,以负载均衡、内核优化等运维手段维持效率

四、启动服务

启动nginx和php-fpm

/usr/local/nginx/sbin/nginx
/usr/local/php-fpm/sbin/php-fpm

命令其他选项

nginx
├── -s选项,向主进程发送信号
|   ├── reload参数,重新加载配置文件
|   ├── stop参数,快速停止nginx
|   ├── reopen参数,重新打开日志文件
|   ├── quit参数,Nginx在退出前完成已经接受的连接请求
├── -t选项,检查配置文件是否正确
├── -c选项,用于指定特定的配置文件并启动nginx
├── -V选项(大写),显示nginx编译选项与版本信息

php-fpm
├── -t选项,检查配置文件是否正确
├── -m选项,显示所有已安装模块
├── -i选项,显示PHP详细信息
├── -v选项,显示版本信息

nginx+php-fpm搭建wordpress

一开始搭建的hexo博客,hexo博客有个缺点,他是用nodejs的服务器,不太稳定,服务器经常挂。所以最后还是决定用nginx+php-fpm搭建一个wordpress站点,这样网站就比较稳定。废话不多说,直接进入主题。

我是用的centos的服务器,下面的一些个命令也是centos的命令,不过其他的也相差不大,主要的是步骤正确就好。

1. 准备 LNMP 环境

安装nginx

使用yum安装nginx

yum install nginx -y

安装完之后修改配置文件 /etc/nginx/nginx.conf

ps:要是配置文件不在这个位置的,可以利用find命令和whereis命令进行查询,参考我另外两篇博文

配置文件参考下面进行更改:

这一步,只需要两处,去除对 IPv6 地址的监听,修改要监听的域名,即:

#listen [::]:80 default_server;
server_name www.***.com;

修改完了之后,就可以启动nginx,查看自己网站首页了,应该看到的是一个nginx测试页面。

启动nginx

nginx

将 Nginx 设置为开机自动启动:

chkconfig nginx on

安装php+php-fpm+php-mysql

这一步有两个选择,安装php7.0版本或是老的版本

安装老的版本比较简单:

yum install php-fpm php-mysql -y

要是想安装php7.0版本,要先添加源,再安装:

如果是centos6,那么执行以下命令

CentOS/RHEL 6.x:

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el6/latest.rpm

如果是centos7.x,那么执行以下命令

CentOS/RHEL 7.x:

rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm

安装php和插件:

可以像上面一样,需要哪个装哪个,也可以全部安装

全部安装:

yum install php70w php70w*

安装需要的:

yum install php70w-common php70w-fpm php70w-opcache php70w-gd php70w-mysqlnd php70w-mbstring php70w-pecl-redis php70w-pecl-memcached php70w-devel

具体可以参考:帐号登录

完了之后启动php-fpm:

service php-fpm start

安装mysql

yum install mysql-server -y

行不通可参考:centos7 mysql数据库安装和配置

2. 安装wordpress

yum install wordpress -y

安装完成后,就可以在 /usr/share/wordpress 看到 WordPress 的源代码了。

由于上面的安装方法默认安装的是英文版,所以我们还要下载中文语言包,如果不需要中文安装可跳过此步骤

wget https://cn.wordpress.org/wordpress-4.8.1-zh_CN.tar.gz
tar -zxvf wordpress*
mv -f wordpress/wp-content/languages /usr/share/wordpress/wp-content/
rm -rf wordpress*

3. 配置

登录mysql,这里初次没有密码,你自己要设置一个密码

mysql -uroot

创建数据库

CREATE DATABASE wordpress;

完成退出

exit;

配置wordpress

进入wordpress目录下,根目录下有一个配置文件wp-config.php,把数据库名,用户,密码配置好就可以,数据库就是刚才建立 的数据库

define('DB_NAME', 'wordpress');
define('DB_USER', 'root');
define('DB_PASSWORD', 'MyPas$word4Word_Press');

修改这三行即可

再次配置/etc/nginx/nginx.conf文件:

完全按照下面配置,修改域名为你的域名即可

server {
listen 80 default_server;
#listen [::]:80 default_server;
server_name www.***.com;
root /usr/share/wordpress;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php index.php;
}

location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

到这一步基本就完成了

nginx重新加载配置

nginx -s reload

访问页面进入wordpress仪表盘

关于nginx和php-fpm的修改用户和用户组的问题

修改nginx和php-fpm的用户和用户组时除了修改

nginx.conf 下的

user *****

和/etc/php-fpm.d/www.conf下的

user = ****

group = ****

修改上面之后,重启nginx和php-fpm,ps -ef|grep … 会发现应用的用户和用户组变了,但是这还能算万事大吉

还要修改一下一些目录下的权限

(以 修改的用户和用户组为nobody为例)

  1. 如 nginx的日志目录 /var/log/nginxchown -R nobody:nobody /var/log/nginx 否则不能不能读写access.logerrorlog

  2. 还有 上传文件用到的一个路径 /var/lib/nginx/tmp/chown -R nobody:nobody /var/lib/nginx 否则上传文件出错,因为保存不了上传的临时文件

3.还有的就是php-fpm的配置文件中

php_value[session.save_handler] = files

php_value[session.save_path] = /var/lib/php/session

设置的session保存的路径,如果你修改了php-fpm的用户和用户组,重启之后,你会发现什么登陆状态,验证码都保存不了,没错session没保存,因为没有修改上面保存session路径的权限

所以应该 让你修改的用户拥有/var/lib/php/session的读写权限,chown 或者chmod 反正让php-fpm的应用用户有权限访问就可以了

扩展:

“ nobody就是一个普通账户,因为默认登录shell是 ‘/sbin/nologin’,所以这个用户是无法直接登录系统的,也就是黑客很难通过漏洞连接到你的服务器来做破坏。此外这个用户的权限也给配置的很低。因此有比较高的安全性。一切都只给最低权限。这就是nobody存在的意义。”

——-摘自 https://blog.csdn.net/gjkun0202/article/details/71156205

查看linux用户列表

cat /etc/passwd|grep -v nologin|grep -v halt|grep -v shutdown|awk -F":" '{ print $1"|"$3"|"$4 }'|more

查看nobody用户所在的组,以及组内成员 groups nobody

查看所有用户组 cat /etc/group

——-摘自 https://www.cnblogs.com/jackyyou/p/5498083.html