存档

‘nginx技巧’ 分类的存档

nginx实现apache的功能php_admin_value open_basedir

2018年8月8日 没有评论

nginx实现apache的功能php_admin_value open_basedir

今天将apache下面的所有虚拟主机站点改成nginx+php-fpm模式运行
考虑到虚拟主机的安全性不受各个站点的影响,所以需要在nginx下实现和apache一样的功能:php_admin_value open_basedir
也就是所说的:防跨目录设置
在apache中,我们只要在加入php_admin_value open_basedir就可以实现
比如:站点路径为/www/webroot/aaa.com
那么就是:php_admin_value open_basedir “/www/webroot/aaa.com:/tmp”
加入tmp是为了不影响用户上传文件,因为会先往临时目录上传

接下来就要进入主题,如何在nginx实现apache的功能php_admin_value open_basedir

查阅了相关文档,本人推荐的实现方式只有1种,方便,快捷,可拓展
当然还有一种其次的推荐方式,先聊聊第一种推荐的吧

======================
第一种:

在每个虚拟主机的server {}的location ~ \.php$ {}中增加:
fastcgi_param PHP_ADMIN_VALUE “open_basedir=/www/webroot/aaa.com/:/tmp/”;
注意,nginx下面,如果你输入的是:aaa.com(而不是aaa.com/)(结尾有/),就会造成是模糊匹配
比如aaa.com额aaa.com.cn,这2个都可以有权限访问

保存,重启nginx+php-ftpm就可以实现效果了
但是,很不幸,如果你有多个虚拟主机站点,访问aaa.com一切正常,访问bbb.com会时而报错:
no input file specified

这个原因是你有多少个虚拟主机,就要把全部虚拟主机的server {}的location ~ \.php$ {}中增加上,不要只增加某一个
否则会报错:no input file specified

一开始我调试的时候,只加了一个aaa.com,其他没加,网上找了很多方法都不行,后来不知脑袋怎么就考虑到要把全部的加上。

===================
第二种:

这种方法不是很推荐,因为需要在每个网站的根目录下增加一个文件,不方便拓展和管理

在每个虚拟主机的根目录下,增加.user.ini文件
比如aaa.com/.user.ini
.user.ini文件的内容就是:
open_basedir=/www/webroot/aaa.com/:/tmp/

当然还需要开启php.ini中的2个参数
sudo vim /etc/php/5.6/fpm/php.ini
开启:
user_ini.filename
user_ini.cache_ttl

重启php-fpm就可以生效了,这个等于不用配置nginx,当然也可以不用重启php-fpm,等待user_ini.cache_ttl设置的时间后,自动生效

这种方法,如果需要把ftp给别人,或者当某个虚拟主机站点受到黑客的时候,会造成.user.ini被串改或者被删除,等待

所以,还需要将文件的权限设置下:
sudo chattr +i /www/webroot/aaa.com/.user.ini
这样ftp里面就无法修改,删除,重命名该文件
当你想要自己修改的时候,进入服务器
sudo chattr -i /www/webroot/aaa.com/.user.ini
就可以重新操作了(+和-参数的区别)
具体chattr命令的参数,可以自行百度

==========================

使用了第二种方法,可以只对某个虚拟主机增加.user.ini,其他虚拟主机访问的时候并不会出现报错:no input file specified
这点和第一种方法不一样,第一种方法必须要把所有的都加上,才能保证每个虚拟主机都能正常访问

php-fpm模式下间歇性无法获取不到$_SERVER或者$_REQUEST数据

2018年7月3日 没有评论

最近安装了一台新的服务器,nginx+php-fpm模式

使用过程中发现$_SERVER或者$_REQUEST(不排除$_POST或者$_GET)间歇性无法获取数据

但是只要重启php-fpm服务就可以解决,但是运行一段时间之后又会反复出现

由此分析应该为php-fpm问题(重启可以解决,个人推测为php-fpm进程问题),一开始以为是当前版本php的bug,后来降低php版本后依然存在,找了很多google资料,都没有遇到类似问题。

花了2天左右时间,对服务器软件配置文件参数逐一排查调试,都没有找到问题所在。

最后,只能从拓展插件上着手,暂时锁定了问题所在:

xcache拓展和opcache拓展建议只开启一个,似乎discuz里面用的是xcache,所以建议只安装xcache
在php-fpm模式下,如果同时安装xcache和opcache,会导致莫名其妙的$_SERVER或者$_REQUEST无法获取数据(间歇性)

所以个人推测:2个都用的话(双层cache)会导致php-fpm的部分进程假死,前段请求发送到假死的进程上后,则无法返回数据,当发送到没假死的进程就可以返回数据(当重启php-fpm服务又正常了)

关闭opcache拓展后,目前运行了近1.5天,已经没有发现此问题。

nginx配置反向代理使用discuz的时候无法加载验证码和安全问答

2018年6月22日 没有评论

今天配置nginx反向代理的时候,发现无法加载验证码和安全问答问题

经过研究和谷歌搜索,发现原来discuz会在头部判断用户来源

所以解决办法是在nginx的虚拟主机配置中加入:

proxy_pass_header User-Agent;

proxy_set_header Host $host;

这样才能正确加载discuz中的验证码和安全问题

如果你也遇到了在nginx中无法加载discuz中的验证码,请使用上方同样的方法,我列举一个虚拟主机的配置例子:

server {
listen 80;
server_name bbs.aaa.com;
location / {
proxy_pass http://bbs.aaa.com:82;
proxy_redirect http://bbs.aaa.com:82/ /;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass_header User-Agent;
proxy_set_header Host $host;

}
access_log logs/bbs.aaa.com.access.log;
}

php-fpm如何合理设置max_chindren和pm模式,包括开启status监听

2018年4月8日 没有评论

说明:以下设置仅供参考,并不代表每个服务器都可以这样设置。

在使用php-fpm+nginx模式的时候,如何合理设置pm模式和max_chindren的值,包括memory_limit的参考设置值;

 

首先,我们开启php-fpm的status来获得执行状态,

sudo vim /etc/php/5.x/fpm/pool.d/www.conf

找到status_path设置为自己想要访问的路径,比如设置为/status,那么通过域名/status即可访问。

保存,然后修改nginx的默认站点配置文件,我这里是default.conf,如果你在fastcgi_params里面已经设置了相关的参数,比如:

fastcgi_pass unix:/run/php/php5.6-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

那么你只需要在default.conf的server段中增加:

location ~ /status$ {include fastcgi_params;}即可,重启nginx和php-fpm,访问:域名/status就可以获得php-fpm的运行状态,比如:

pool: www
process manager: dynamic
start time: 07/Apr/2018:20:44:53 -0700
start since: 187
accepted conn: 5570
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 25
active processes: 7
total processes: 32
max active processes: 54
max children reached: 0
slow requests: 0

具体的参数代表含义,可以自行百度搜索。

使用htop命令查看单个php-fpm所申请的VIRT大小,我32G服务器是400左右(实际要除以8=M,就是:50M左右),如果按照每个进程消耗50M*1.5倍=75M左右,如果你的服务器内存是32G,我们假设可用于php-fpm的内存为60%=20G,则:20*1024/75=273,所以,一般我们建议max_chindren最大为273,最好还是设置为:8的倍数,所以我设置为256.

然后我们可以根据域名/status的结果来合理设置其他参数(pm.start_servers和pm.min_spare_servers和pm.max_spare_servers)

在php.ini中,我们可以看到memory_limit有一句这样的原文,Maximum amount of memory a script may consume (128MB),就是说单个进程使用的最大内存大小,这个参数吧,当然不能低于刚刚计算的75M了,一般我们可以设置为3倍,则75*3=225M左右(建议:128,256,512,1024…)

这里假如有攻击的话,max_chindren=256,memory_limit=256,256*256=64G,很明显会导致内存爆满,所以如果想又保持性能,又能一定程度上防止内存爆满,可以将max_chindren设置的低一点,memory_limit可以设置为每个进程消耗的值(一般不建议低于128M吧,如果是独立服务器的话)。

当然,如果php.ini里面的memory_limit设置后无效,你可以关注下:/etc/php/5.x/fpm/pool.d/www.conf中的php_admin_value[memory_limit] =参数。

=============================

我们关注下 PHP-FPM 的运行方式:
pm = static模式:

始终保持一个固定数量的子进程,这个数由pm.max_children定义,这种方式很不灵活,也通常不是默认的。
优点是不用动态的判断负载情况,提升性能;缺点是多占用些系统内存资源。在内存足够的前提下性能最强
用此模式每天需要设置固定时间重启php
pm = dynamic模式:

启动时,会产生固定数量的子进程(由pm.start_servers控制)可以理解成最小子进程数,而最大子进程数则由pm.max_children去控制,OK,这样的话,子进程数会在最大和最小数范围中变化,还没有完,闲置的子进程数还可以由另2个配置控制,分别是pm.min_spare_servers和pm.max_spare_servers,也就是闲置的子进程也可以有最小和最大的数目,而如果闲置的子进程超出了pm.max_spare_servers,则会被杀掉。
pm = ondemand模式:

这种模式和pm = dynamic相反,把内存放在第一位,他的工作模式很简单,每个闲置进程,在持续闲置了pm.process_idle_timeout秒后就会被杀掉,有了这个模式,到了服务器低峰期内存自然会降下来,如果服务器长时间没有请求,就只会有一个php-fpm主进程,当然弊端是,遇到高峰期或者如果pm.process_idle_timeout的值太短的话,无法避免服务器频繁创建进程的问题,因此pm = dynamic和pm = ondemand谁更适合视实际情况而定。
PHP-FPM 子进程数量,是不是越多越好?

当然不是,pm.max_chindren,进程多了,增加进程管理的开销以及上下文切换的开销。

更核心的是,能并发执行的 php-fpm 进程不会超过 cpu 个数。

如何设置,取决于你的代码

如果代码是 CPU 计算密集型的,pm.max_chindren 不能超过 CPU 的内核数。
如果不是,那么将 pm.max_chindren 的值大于 CPU 的内核数,是非常明智的。
国外技术大拿给出这么个公式:

在 N + 20% 和 M/m 之间。

N 是 CPU 内核数量。
M 是 PHP 能利用的内存数量。
m 是每个 PHP 进程平均使用的内存数量。
适用于 dynamic 方式。

static方式:M/(m * 1.2)

当然,还有一种保险的方式,来配置 max_children。适用于 static 方式。

先把 max_childnren 设置成一个比较大的值。
稳定运行一段时间后,观察 php-fpm 的 status 里的 max
active processes 是多少
然后把 max_children 配置比它大一些就可以了。
pm.max_requests:指的是每个子进程在处理了多少个请求数量之后就重启。

这个参数,理论上可以随便设置,但是为了预防内存泄漏的风险,还是设置一个合理的数比较好

=============================

所以,我的服务器32G内存设置为:

memory_limit = 256M

pm = dynamic
pm.max_children = 256
pm.start_servers = 32
pm.min_spare_servers = 16
pm.max_spare_servers = 32

根据php-fpm的status监控数据显示,服务器状态运行良好。

关于nginx+php-fpm中的一些优化(比如502+504错误)

2017年8月31日 没有评论

首先检查一下ulimit -n的值,SSH输入命令:

# ulimit -n
返回:65535

1、提升服务器的文件句柄打开

SSH命令:# vi /etc/security/limits.conf,在结尾处添加以下内容:

* soft nofile 65535
* hard nofile 65535

2、提升nginx的进程文件打开数

# vi /usr/local/nginx/conf/nginx.conf
查看 worker_rlimit_nofile 65535;

3、修改 php-fpm.conf 配置文件

前面确认了 ulimit -n 值为 65535,/usr/local/php/etc/php-fpm.conf 中的选项 rlimit_files 确保和此数值一致。

rlimit_files = 65535

4、修改 sysctl.conf

# vi /etc/sysctl.conf

底部添加

fs.file-max=65535

Edit…

vim /etc/php5/fpm/pool.d/www.conf

Set…

request_terminate_timeout = 300

Changes in Nginx Config

To increase the time limit for example.com by

vim /etc/nginx/sites-available/example.com
location ~ \.php$ {
	include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
	fastcgi_read_timeout 300; 
}

If you want to increase time-limit for all-sites on your server, you can edit main nginx.conf file:

vim /etc/nginx/nginx.conf

Add following in http{..} section

http {
	#...
        fastcgi_read_timeout 300; 
	#...
}

另外设置/etc/php/5.6/fpm/pool.d/www.conf中的request_terminate_timeout为0或者300(0s为关闭,就是无限执行下去。)

另外如何设置www.conf中的nginx运行方式:(老版本中apache-like是现在的dynamic)

如果设置成static,php-fpm进程数自始至终都是pm.max_children指定的数量,不再增加或减少。

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

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

这里先说一下涉及到这个的几个参数,他们分别是pmpm.max_childrenpm.start_serverspm.min_spare_serverspm.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之间。

css.php