前言#
将服务器上的 Apache 升级到 2.4.46 后,内充占用率飙涨,改了 MaxConnectionPerChild 配置到 50 也不见效。2G 的内存占用率已经超过 90,Apache 吃掉了差不多 1G 内存。systemctl restart httpd 以后,很快又把内存吃回去。虽然一直都遇到内存占用的问题,但之前没有这么严重,也就凑活着用了。每次想换 nginx 都觉得太折腾就作罢。现在这情况只能强行折腾了,服务器都卡的用不了了。下面分享一下更换 web 服务器的过程。
过程#
其实过程也比较简单,停了 apache。
systemctl stop httpd
systemctl disable httpdbash安装 nginx,直接用 yum 安装即可。启动并设置开机启动,同时确保 php-fpm 也启动了。
yum install nginx
systemctl start nginx
systemctl enable ninxbash剩下的就是配置了,配置文件路径 /etc/nginx/nginx.conf。nginx 支持模块化的配置,你可以把不同功能的配置写到不同的文件里面,然后用 include 引入。单独的 conf 文件要放到 /etc/nginx/conf.d 文件夹里。如果你不想创建单独的文件,就把配置写在 nginx.conf文件夹里也可以,是一个 server {}。需要特别注意的是你的配置要写到 include /etc/nginx/conf.d/*.conf 这一句的 前面。我一开始就是看错成后面,白白乱折腾了一阵子。
然后 nginx 的配置其实还是比较好理解的,但是不支持 .htaccess。关于配置我这里就不细说了,我也就东拼西凑搞了个差不多的,目前看来基本能用了,有些问题可能后期使用中才能慢慢发现,这里就给大家贴一下我现在的配置。
server {
#http重定向到https
listen 80;
listen [::]:80;
server_name www.clloz.com clloz.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.clloz.com clloz.com;
#网站根目录
root /var/www/html;
#https
ssl_certificate ssl/3793755_www.clloz.com.pem;
ssl_certificate_key ssl/3793755_www.clloz.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #使用此加密套件。
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #使用该协议进行配置。
ssl_prefer_server_ciphers on;
# 安全标头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-Xss-Protection 1;
# 禁用目录列表
autoindex off;
# 限制请求次数
#limit_req_zone $binary_remote_addr zone=WPRATELIMIT:10m rate=2r/s;
#location ~ \wp-login.php$ {
# limit_req zone=WPRATELIMIT;
#}
#隐藏 nginx 版本.
server_tokens off;
#隐藏 PHP 版本
fastcgi_hide_header X-Powered-By;
proxy_hide_header X-Powered-By;
# 禁止访问敏感文件
location ~ /\.(svn|git)/* {
deny all;
access_log off;
log_not_found off;
}
location ~ /\.ht {
deny all;
access_log off;
log_not_found off;
}
location ~ /\.user.ini {
deny all;
access_log off;
log_not_found off;
}
# 禁止直接访问php文件
# location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ {
# deny all;
# access_log off;
# log_not_found off;
# }
#固定链接交给php-fpm处理
location / {
index index.php index.html index.htm;
try_files $uri $uri/ /index.php?$args;
}
# 禁止访问指定类型文件
location ~ \.(ini|conf)$ {
deny all;
}
# 允许内部分 wp-includes 目录的 .php 文件
location ~* ^/wp-includes/.*\.(php|phps)$ {
internal;
}
#禁止访问 wp-config.php install.php 文件
location = /wp-config.php {
deny all;
}
location = /wp-admin/install.php {
deny all;
}
# 禁止访问 /wp-content/ 目录的 php 格式文件 (包含子目录)
location ~* ^/wp-content/.*.(php|phps)$ {
deny all;
}
# 固定连接的php处理
location ~* ^/s/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* ^/programming/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* ^/essay/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* ^/sweets/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* ^/links/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* ^/abouts/.*.(php|phps)$ {
#deny all;
return 404;
}
location ~* /(?:uploads|files|wp-content|wp-includes|akismet)/.*.php$ {
deny all;
access_log off;
log_not_found off;
}
# 错误页面设置
error_page 403 /403.html;
location = /403.html {
root /etc/nginx/error_pages;
internal;
}
error_page 404 /404.html;
location = /404.html {
root /etc/nginx/error_pages;
internal;
}
error_page 500 /500.html;
location = /500.html {
root /etc/nginx/error_pages;
internal;
}
error_page 503 /503.html;
location = /503.html {
root /etc/nginx/error_pages;
internal;
}
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;
}
}bash还有一个没有解决的问题就是,php 类型的 url 都交给 php-fpm 处理,当找不到 url 的时候,php-fpm 会直接返回一个 file not found。我们在 nginx 中设置的 404 页面也不会显示。我本来想看看 php-fpm 能不能设置默认 404 页面的,不过没找到方法。nginx 这边也没设么很好的处理方法,我最后的解决办法就是用 location 来过滤固定链接,只要检测到是固定链接,同时路径是以 php 结束的直接返回 404,固定链接一共也就几种(取决于你有几个一级分类目录)。这个方法有一个瑕疵就是根目录下的以 php 结尾的路径无法过滤,因为根目录下有些 php 是要访问的,我们没法一刀切。不过目前也没有找到其他的好办法,就先这样吧,问题也不大。
更新:根目录下路径下的 php 结尾的路径我用正则表达式 ^/(?!(wp-|xmlrpc))[^/]*php$ 进行了处理,把除了 wp- 开头的和 index.php,xmlrpc.php 以外的全部过滤了。除了 wp-content,wp-includes,wp-admin 路径下,其他的带 / 的路径访问 php 都直接返回 404,正则表达式为 ^/(?!wp-content|wp-includes|wp-admin|editormd).*/.*php$。
这里顺便说一下 location 配置指令格式为:location [ = | ~ | ~* | ^~ ] uri {...}。这里的 uri 分为标准 uri 和正则 uri,两者的唯一区别是 uri 中是否包含正则表达式。uri 前面的方括号中的内容是可选项,解释如下:
=:用于标准uri前,要求请求字符串与uri严格匹配,一旦匹配成功则停止~:用于正则uri前,并且区分大小写~*:用于正则uri前,但不区分大小写^~:用于标准uri前,要求Nginx找到标识uri和请求字符串匹配度最高的location后,立即使用此location处理请求,而不再使用location块中的正则uri和请求字符串做匹配
由于我只是更换 web 服务器,所以还算比较简单,如果你是从头安装,那么你可以看我之前的文章,或者参考腾讯云的这篇教程:手动搭建 LNMP 环境(CentOS 7) ↗
更新内存占用的主要原因是 php-fpm 进程过多,配置一下 /etc/php-fpm.d/www.conf。
pm = dynamic #指定进程管理方式,有3种可供选择:static、dynamic和ondemand。
pm.max_children = 16 #static模式下创建的子进程数或dynamic模式下同一时刻允许最大的php-fpm子进程数量。
pm.start_servers = 10 #动态方式下的起始php-fpm进程数量。
pm.min_spare_servers = 8 #动态方式下服务器空闲时最小php-fpm进程数量。
pm.max_spare_servers = 16 #动态方式下服务器空闲时最大php-fpm进程数量。
pm.max_requests = 2000 #php-fpm子进程能处理的最大请求数。
pm.process_idle_timeout = 10s
request_terminate_timeout = 120bash我是将 max_spare_servers 设置为 10,这样最多同时存在 10 个 php-fpm。