网站搬家笔记,记录lnmp生产环境搬家及优化升级过程

2018年8月10日最后更新

自己的一个网站现在日访问量3.2万IP 3.5万UV 15万+PV
跑在最低配的阿里云服务器上,虽然经过大量优化,但是已经很吃力了
阿里云是越来越贵,等你在我这儿住习惯后慢慢敲你竹杠的感觉....搬家吧

开这篇笔记,记录生产过程部署及调优,生产环境的部署一定是根据业务需求来确定的
不能小马拉大车,容易失控翻车
也不能大马拉小车,浪费饲料


我的网站程序为php,我重新部署生产环境主要考虑网站以最低成本应付日常访问,保持较低的系统负载,避免php-fpm崩溃导致网站502,避免关键的mysql数据库崩溃及过高的CPU占用率,
网站生产环境中的mysql数据库是本次优化的重点,其次是php-fpm

有个大胆的计划:
将cache\静态文件\mysql放入高速的本地盘,利用其高IO特性
为了保证安全,采用脚本或者lsyncd对数据目录进行实时增量备份到云磁盘,如果本地盘出问题,可以修改配置文件,立即切换
可能很多人会觉得这个方案很白痴,数据放本地盘极为不安全,连官方页面上都是建议本地盘用于不太重要的数据读写...
我之所以有这个想法是因为我搬家后的云服务器云磁盘的IO比较低,但是本地盘的IO性能是云磁盘的20倍,用本地盘对数据库的性能提升会非常明显,所以打算在这次搬家后实验下

---------------------------
1\服务器操作系统基本配置(操作系统centos 6.8 64bit)
---------------------------
ssh登录上服务器:
挂载CDS云磁盘->>>参照http://xiaohost.com/1376.html
加强linux服务器安全的措施:修改ssh端口禁用root账户密码登录,限制使用密匙登录->>>参照http://xiaohost.com/2414.html

yum install wget screen -y && screen -S lnmp
sudo yum check-update || sudo yum update -y
yum groupinstall -y 'Development Tools'
yum install -y epel-release
yum install -y perl perl-devel perl-ExtUtils-Embed libxslt libxslt-devel libxml2 libxml2-devel gd gd-devel GeoIP GeoIP-devel

---------------------------
2\安装lnmp
---------------------------
需求:
(1)使用IO高的本地盘存放数据库文件(至于数据库的安全性,后面再讲怎么进行加强)
(2)使用ngx_cache_purge进行缓存(lnmp一键安装包默认不带此模块)
备注:原计划再安装pagespeed ,综合考虑,暂时安装,对低配置服务器压力大

由于以上需求的原因,要对lnmp一键包的配置进行修改
先安装screen并切换到screen下进行后续操作

新建一个目录专门放lnmp1.4的安装包便于管理

cd / && mkdir codefiles && cd codefiles

修改军哥的一键包安装安装命令,下载解压后不立即执行安装程序,我们需要手动修改配置

wget -c http://soft.vpser.net/lnmp/lnmp1.4.tar.gz && tar zxf lnmp1.4.tar.gz && cd lnmp1.4

准备工作:下载ngx_cache_purge-2.3.tar.gz解压后放入lnmp1.4目录内(当前目录)

cd src && wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz && tar zxvf ngx_cache_purge-2.3.tar.gz && rm -rf ngx_cache_purge-2.3.tar.gz && cd ..

修改lnmp根目录下(一键包解压后的lnmp1.x目录下)的lnmp.conf文件,将需要安装的模块加入Nginx_Modules_Arguments=""
另外,为了以后需要增加前端做反代的时候扩展,启用Nginx自带的Module ngx_http_realip_module

vi lnmp.conf

修改配置文件为:

Download_Mirror='https://soft.vpser.net'

Nginx_Modules_Options='--add-module=/codefiles/lnmp1.4/src/ngx_cache_purge-2.3 --with-http_realip_module'
PHP_Modules_Options=''

##MySQL/MariaDB database directory##
MySQL_Data_Dir='/mnt/mysql/var'
MariaDB_Data_Dir='/mnt/mariadb/var'
##Default website home directory##
Default_Website_Dir='/home/wwwroot/default'

Enable_Nginx_Openssl='y'

配置文件中,替换了数据库原来的默认地址/usr/local/ ,由于本地磁盘是挂载到/mnt文件夹上,所以修改了路径
-----------------------
这里先暂停下,去云服务器管理控制台,做一个"系统盘"的快照,方便等下有问题重置安装lnmp前的环境,防止之前的工作白费了
-----------------------
接着安装lnmp
先更新下系统

yum update -y

然后启动安装脚本

./install.sh lnmp

选择需要安装的数据库,输入数据库root账户密码
选择要安装的php版本

然后..........等着安装完成

使用军哥的lnmp一键安装包安装lnmp
系统最终环境为
centos 6.8 64bit
Nginx 1.12.2
MariaDB 10.1.23
php 5.5.38

---------------------------
3\安装网站需要用到的其他软件
---------------------------
先删除之前安装lnmp不需要保留的东西

rm -rf /codefiles/lnmp1.4.tar.gz && rm -rf /codefiles/lnmp1.4/src/ngx_cache_purge-2.3.tar.gz

安装mercached

cd /codefiles/lnmp1.4/ && ./addons.sh

wordpress 的mercached插件下载地址:
https://github.com/tollmanz/wordpress-pecl-memcached-object-cache
下载并解压得到的 object-cache.php,上传到 wp-content 目录即可开启 memcached 缓存。
上述下载地址失效的话,可以在这里下载wordpress-pecl-memcached-object-cache-master

mercached官方探针下载:
http://pecl.php.net/get/memcache-3.0.8.tgz
解压后,里面有一个 memcache.php 文件,编辑并找到如下代码:

define('ADMIN_USERNAME','memcache');    // Admin Username
define('ADMIN_PASSWORD','password');    // Admin Password
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
 
$MEMCACHE_SERVERS[] = 'mymemcache-server1:11211'; // add more as an array
$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array

修改为:

define('ADMIN_USERNAME','memcache');    // Admin Username 登录名称,自行修改
define('ADMIN_PASSWORD','password');    // Admin Password 登录密码,自行修改
define('DATE_FORMAT','Y/m/d H:i:s');
define('GRAPH_SIZE',200);
define('MAX_ITEM_DUMP',50);
//下面是定义memcached服务器,一般我们是单机部署,所以注释掉一行,并将服务器地址根据实际修改,比如本文是127.0.0.1
$MEMCACHE_SERVERS[] = '127.0.0.1:11211'; // add more as an array
//$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; // add more as an array

上传到网站私密目录(临时测试可以放到根目录),然后通过前台访问 memcache.php 这个文件,输入上面的用户名和密码即可看到 memcached 状态:
bash,CentOS,curl,iptable,iptables,linux,lnmp,lnmp 安装,lnmp日志,Mariadb,Memcached,my.cnf,MySQL,MySQL配置文件,netstat,Nginx,php-fpm.conf,php-fpm配置,php-fpm配置文件,SSL,wget,wordpress,Wordpress 网站服务器环境搭建,云主机,域名,服务器,服务器安全,监控宝,
如果发现页面可以打开,但是里面没有 Hits 数据,说明 WordPress 并没有成功连接到 memcached,这时候我们可以在 wp-config.php 加入如下参数:

global $memcached_servers;
$memcached_servers = array(
    array(
        '127.0.0.1', // Memcached server IP address
         11211        // Memcached server port
    )
);

实际的 memcached 监听 IP 和端口,通过命令查看

netstat -nutlp | grep memcache

启用opcache优化php执行(lnmp已经有,但未启用,使用下面命令启用即可)

./addons.sh install opcache

copy配置文件到新服务器备用
Nginx主配置文件
/usr/local/nginx/conf/nginx.conf
虚拟主机配置文件
/usr/local/nginx/conf/vhost/域名.conf
MySQL配置文件(Mariadb的配置文件与mysql通用,但是新环境所以决定使用默认的配置进行修改)
/etc/my.cnf
PHP配置文件
/usr/local/php/etc/php.ini
php-fpm配置文件
/usr/local/php/etc/php-fpm.conf

SNMP监控配置文件
/etc/snmp/snmpd.conf

coretab 的计划任务,同时查看原服务器定时执行的任务相关脚本,可能之前对脚本进行过修改,需要在新服务器使用

*/5 * * * * /bin/bash /codefiles/lnmp1.4/tools/checkmysql.sh
*/5 * * * * /bin/bash /codefiles/lnmp1.4/tools/check502.sh
00 03 * * * /bin/bash /codefiles/lnmp1.4/tools/cut_nginx_logs.sh
00 23 * * 3 /bin/bash /codefiles/lnmp1.4/tools/backup.sh

---------------------------
4\网站配置
---------------------------
(1)新建vhost/绑定域名/开启SSL/将原来的php/Nginx配置文件拷贝过来,优化php及Nginx配置
(2)http://xiaohost.com/1138.html Centos下lnmp正确iptables配置规则

---------------------------
5\lnmp日志的记录与处理
---------------------------
(1)使用脚本设定coretab任务,对日志进行切割按天保存,30天后自动删除,参照http://xiaohost.com/1201.html
(2)禁用lnmp的mysql日志功能防止占满磁盘导致出错,参考http://xiaohost.com/119.html

---------------------------
6\防火墙规则
---------------------------
注意iptables规则与云主机的安全组相匹配,参照http://xiaohost.com/1138.html
另外,如果服务器或者程序需要给用户发邮件,需要开启25端口,如果用第三方,开启465
注意:check502和checkmysql脚本检测到php和mysql异常时,服务器会发送邮件通知自己
如果默认使用linux当前登录用户发信,通常会被当成垃圾邮件,需要指定发件人邮箱信息
命令:vi /etc/mail.rc编辑内容如:

set from=username@126.com
set smtp=smtp.126.com
set smtp-auth-user=username
set smtp-auth-password=password
set smtp-auth=login

注意配置中的smtp-auth-password不是邮箱登录密码,是邮箱服务器开启smtp的授权码,每个邮箱开启授权码操作不同(网易126邮箱开启菜单:设置-> 客户端授权密码)。
---------------------------
7\开启snmp,使用第三方监控平台对服务器进行监控,以便及时掌握服务器状态(有精力,后期可以自己搭建监控平台,使用)
---------------------------

yum install net-snmp net-snmp-devel -y

snmp分v2c和v3,各自的数据验证方式不同

V2版验证方法
首先清空默认配置文件,里面太多无关内容

> /etc/snmp/snmpd.conf

然后编辑配置文件

vi /etc/snmp/snmpd.conf

加入以下内容

rocommunity public 127.0.0.1
rocommunity public 192.168.1.1
# 如果您使用的是采集器,以下IP应该是安装采集器的服务器的IP
rocommunity public 60.195.252.107
rocommunity public 60.195.252.110

将上述的192.168.1.1更改为服务器IP,public可替换为您希望的验证字符串。
之前清空的默认的配置文件里会有一些权限控制的配置,如果您有这个需求,请自行参考CentOS的man文档加入相关配置。

V3验证方法
运行之前请先停用net-snmp服务,否则无法添加,命令如下:

service snmpd stop

使用如下命令创建一个snmpv3用户(权限为只读,加密方式为MD5,用户名为jiankongbao,密码为snmp@jiankongbao):

net-snmp-config --create-snmpv3-user -ro -A snmp@jiankongbao -a MD5 jiankongbao

运行Net-SNMP

service snmpd start
chkconfig snmpd on

V2c版本检测
使用如下命令查看161UDP端口是否打开:

netstat –antupl

在另外任意一台机器上执行如下命令(请将commity换成您自己的字符串,tartget_ip换为被监控服务器的IP):

snmpwalk -v2c –ccommity target_ip

如果出现长串数字,则说明mib没有安装好。

V3版本检测

snmpwalk -v 3 -u jiankongbao -a MD5 -A "snmp@jiankongbao" -l authNoPriv 127.0.0.1 sysDescr

我们可以使用snmpwalk来检测snmp服务是否正常开启,命令如下:

snmpwalk -v 3 -u jiankongbao -a MD5 -A "snmp@jiankongbao" -l authNoPriv 127.0.0.1 sysDescr

如果一切正常,就会返回正常结果。
如果提示命令无效 使用

yum install net-snmp-utils -y

安装即可

snmp防火墙(iptables)设置
V2版

iptables -L -n

允许UDP的161端口

iptables -I INPUT -p udp --dport 161 -j ACCEPT

高级设置:以下防火墙规则限制为360和监控宝的snmp监控服务器IP,限定只有这些IP能获取信息

iptables -I INPUT -p udp -s 60.195.252.107 --dport 161 -j ACCEPT;iptables -I INPUT -p udp -s 60.195.252.110 --dport 161 -j ACCEPT;iptables -I INPUT -p udp -s 127.0.0.1 --dport 161 -j ACCEPT;iptables -I INPUT -p udp -s 45.63.121.42 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 101.199.100.150 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 220.181.150.98 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 180.153.229.230 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 220.181.150.125 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 103.28.11.237 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 103.28.10.244 --dport 161 -j ACCEPT;iptables -A INPUT -i eth0 -p udp -s 103.28.10.245 --dport 161 -j ACCEPT

---------------------------
8\完善服务器备份
---------------------------
(1)使用coretab每天凌晨执行脚本,将本地磁盘/mnt目录增量备份到云磁盘(排除缓存目录,只备份数据库),覆盖,本地盘出问题,修改配置,然后使用云磁盘的备份
(2)使用云磁盘自动快照功能,每天凌晨自动对系统盘及数据盘进行快照(由于本地盘无法提供快照功能,而数据库又跑在上面,所以需要上一步的每天备份数据库至数据盘,要注意(1)(2)的时间配合好,先备份数据库到数据盘,再对数据盘进行快照)
(3)使用脚本每月自动打包备份数据库及网站文件(不含缓存)到远程FTP服务器或其他云提供的对象存储中,定期删除历史备份,保存时间30天

---------------------------
9\优化网站
---------------------------
(1)网站动静完全分离 参考http://xiaohost.com/2473.html
(2)全站https 这个..实在没有难度,就不写出来了吧

----------------拓展:为什么用Nginx+php-fpm,不用Apache+MOD_PHP--------------------
Nginx+PHP-FPM很容易实现动静分离,支持upstream配置PHP-FPM集群实现负载均衡以及故障转移
Nginx+PHP-FPM相对Nginx+Apache(libphp5.so)来说,PHP-FPM更灵活,
在php-fpm.conf里可以配置监听不同端口的多个pool
每个pool又可以自由配置PHP-FPM工人进程数pm.max_children
一个pool里的工人进程繁忙不会影响到另一个pool
而且一台服务器上可以运行多个版本的PHP-FPM,借助Nginx的upstream功能,PHP-FPM非常容易横向扩展。

Nginx返回502 Bad Gateway错误不是因为Nginx的问题,而是因为后端的问题.
比如后端PHP-FPM在处理一个请求时进程崩溃了,那么Nginx就会返回502错误.
可行的方法是:用fastcgi_next_upstream配置让Nginx把请求转移给另一个upstream处理.

fastcgi_next_upstream error timeout invalid_header http_500 http_502 http_504;

PHP-FPM配合Nginx还可以把I/O密集操作分离出来,减少阻塞对整个PHP应用的影响.
用户下载和curl请求是典型的I/O密集型操作,因为耗时主要发生在网络I/O和磁盘I/O.
需要PHP认证的下载操作可以委托为Nginx的AIO线程池:
header("X-Accel-Redirect: $filepath");
至于curl操作,比如可以建立一个监听9001端口的名为io的PHP-FPM进程池(pool),
专门负责处理curl操作(通过Nginx分发),避免curl操作阻塞到监听9000端口的www进程池.
这时io进程池多开点进程也无所谓:

nginx.conf配置

;访问io.php的请求都交给监听9001的PHP-FPM进程池处理
location = /io.php {
    include fastcgi_params;
    fastcgi_pass 127.0.0.1:9001;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
;php-fpm正常脚本由静态www池处理,阻塞脚本由动态io池处理
[www]
;名为www的进程池监听9000端口,常驻进程数量为固定4个
listen = 127.0.0.1:9000
pm = static
pm.max_children = 4
[io]
;名为io的进程池监听9001端口,进程数常驻4个,最大8个
listen = 127.0.0.1:9001
pm = dynamic
pm.max_children = 8
pm.start_servers = 4
pm.min_spare_servers = 4
pm.max_spare_servers = 4

其中I/O密集这个进程池[io]采用动态的prefork进程,比如这里是繁忙时8个,空闲时4个.
利用PHP-FPM提供的池的隔离性,分离计算密集和I/O密集操作,可以减少阻塞对整个PHP应用的影响.