LNMP 分布式集群(一):Nginx+PHP平台搭建与负载均衡配置

4,483 阅读3分钟

前言

本篇文章是对Nginx学习过程的一个总结提升,所谓LNMP即Linux+Nginx+MySQL+PHP,而分布式是指把一项工作划分成不同的业务到多个不同的服务器,使得他们各自进行自己的处理,共同完成该项工作,而集群就是将多台服务器集中起来以实现负载均衡和高可用性,分布式和集群各有优缺点,将优点结合,就形成了分布式集群。将一个工作分成多个业务分布到集群中处理。除了LNMP还可以部署LNAMP(加入Apache服务器处理动态资源,Nginx处理静态资源和反向代理),这里就不多说了。

把我坑掉的是:起初我用了Nginx的1.16.1版本,PHP的5.6.27,结果他俩不能正常合作,于是Nginx退回到1.10.3。

LNMP分布式部署

由图可知,我们创建了9台服务器各司其职,每台服务器都代表了一项服务。

编号 IP 服务器
1 192.168.177.11 Nginx(www.itshop.test):负载均衡
2 192.168.177.12 Nginx(file.itshop.test):静态文件缓存
3 192.168.177.13 Nginx+PHP(upload.itshop.test):文件上传
4 192.168.177.14 Nginx+PHP
5 192.168.177.15 Nginx+PHP
6 192.168.177.16 NFS:文件存储
7 192.168.177.17 MySQL(主)
8 192.168.177.18 MySQL(从)
9 192.168.177.19 Memcached:数据缓存

部署

Linux 服务器的部署

这一节的详细信息请看文章:在CentOS中通过源码编译安装Nginx

install centos minimal

需要先控制好每个虚拟机的内存配额,防止物理机内存不足,若物理机有8G内存,推荐每台虚拟机分配512MB。

在安装的时候开启网络

建议安装net-tools:yum -y install net-tools,也建议此时为系统换tuna的源

在完成了1号服务器的Linux系统安装之后克隆出其他4台不需要安装的Nginx服务器,然后再部署Nginx再克隆其他4台需要Nginx的服务器,基本流程如图:

虚拟机克隆流程

每台服务器都要注意按照需求设置网络,主要就是网络的静态配置。

我们编写可以一个SHELL脚本,也可以手动配置:

#! /bin/bash
ens33=/etc/sysconfig/network-scripts/ifcfg-ens33
sed -i 's/BOOTPROTO=.*/BOOTPROTO=\"static\"/g' $ens33
sed -i '$aIPADDR=192.168.177.1'$1'' $ens33
sed -i '$aNETMASK=255.255.255.0' $ens33
sed -i '$aGATEWAY=192.168.177.2' $ens33
sed -i '$aDNS1=192.168.177.2' $ens33
service network restart

然后使用./network-settings.sh 1设置服务器的网络,

sed 命令中,i表示直接编辑,s表示替换,$匹配最后的行尾,a表示追加,详情请看:man.linuxde.net/sed,替换可以使用sed -i 's/IPADDR=.*/IPADDR=192.168.177.1'$1'/g' $ens33

下面就要进行正式的部署了,在这之前我们回顾一张图,这是需要记住的架构:

架构(序号代表IP地址:192.168.177.1X)

Nginx 环境的部署

首先在1号服务器中安装Nginx(参考在CentOS中通过源码编译安装Nginx):

【友情提示,尽可能按照本文的软件版本配置,如Nginx为1.10.3,PHP为5.6.27,否则会很要命,因为版本不匹配会出现很大问题,要么都用最新版,要么按照本文的配置来】

wget http://nginx.org/download/nginx-1.10.3.tar.gz
tar -zxvf nginx-1.10.3.tar.gz
yum -y install gcc pcre-devel openssl-devel
cd nginx-1.10.3
./configure --preifx=/usr/local/nginx --with-http_ssl_module --with-http_realip_module
make && make install
ln -s /usr/local/nginx/sbin/nginx /usr/local/sbin/nginx
vi /etc/init.d/nginx # 此时参考之前的文章写一个启动脚本于:/etc/init.d/nginx
chmod +x /etc/init.d/nginx
chkconfig --add nginx
# 创建用户www和站点目录/data/www
useradd -s /sbin/nologin -M www
mkdir -p /data/www
cp /usr/local/nginx/html/* /data/www
chown -R www:www /data/www
vi /usr/local/nginx/conf/nginx.conf
# 配置用户
user www
# 修改server块
server {
    listen 80;
    server_name localhost;
    root /data/www;
    index index.html index.htm;
}
service nginx start
# 更新和配置防火墙
systemctl stop firewalld
systemctl disable firewalld
firewall-cmd --state 
yum -y install iptables-services
systemctl enable iptables
systemctl start iptables
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
service iptables save

useradd命令,-M:不要自动建立用户的登入目录;-s:指定用户登入后所使用的shell; chown命令,参数有用户:组:指定所有者和所属工作组。当省略“:组”,仅改变文件所有者;-R或——recursive:递归处理 user 用户 [用户组];命令配置服务器运行的用户或组

然后克隆虚拟机2号和3号,注意执行脚本配置网络。

这之后修改本地主机的hosts文件,例如我的MacBook Pro上的vi /etc/hosts

192.168.177.11 itshop.test
192.168.177.11 www.itshop.test
192.168.177.12 file.itshop.test
192.168.177.13 upload.itshop.test

Nginx + PHP 服务器的搭建

在3、4、5号的服务器中安装PHP,其中3号服务器提供文件上传服务,包括对图片压缩、生成缩略图、添加水印等,最后保存到6号的文件存储服务器中,4、5号服务器是一个集群用于执行网站的脚本程序。

本身来说PHP与Apache的结合是最完美的(PHP以模块方式工作),但是这里我们要用到Nginx(PHP以CGI方式工作),所以需要配置FastCGI,详细请阅读Nginx+Php-fpm 运行原理详解

在3号服务器中安装PHP:

# 安装依赖,需自行下载[libmcrypt-2.5.8.tar.gz](https://sourceforge.net/projects/mcrypt/files/Libmcrypt/2.5.8/libmcrypt-2.5.8.tar.gz/download)
yum -y install gcc-c++ libxmk2-devel curl-devel libjpeg-devel libpng-devel freetype-devel
tar -zxf libmcrypt-2.5.8.tar.gz
cd libmcrypt-2.5.8
./configure && make && make install && cd ..
# 编译安装PHP(演示用,我们采用的是php-5.6.27)
wget https://www.php.net/distributions/php-7.4.0.tar.gz
tar -zxf php-5.6.27.tar.gz
cd php-5.6.27
./configure --prefix=/usr/local/php --enable-fpm --with-zlib --enable-zip --enable-mbstring --with-mcrypt --with mysql \
--with-mysqli --with-pdo-mysql --with-gd --with-jpeg-dir --with-png-dir  \
--with-freetype-dir --with-curl --with-openssl --with-mhash --enable-bcmath \
--enable-opcache && make && make install
# 配置Nginx 和PHP
cp php.ini-production /usr/local/php/lib/php.ini
vi /usr/local/php/lib/php.ini # 配置时区为PRC date.timezone=PRC
cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm # 创建服务脚本、配置开机启动
chmod +x /etc/init.d/php-fpm
chkconfig --add php-fpm
cd /usr/local/php/etc
cp php-fpm.conf.default php-fpm.conf
vi php-fpm.conf 
# 更改 [www] 下的配置
user=www # 子进程工作用户
group=www
listen=/dev/shm/php-cgi.sock # 监听sock文件
listen.owner=www # socket 文件的所有者
listen.group=www
service php-fpm start
vi /usr/local/nginx/conf/nginx.conf
# 在server块中配置:
index index.html index.htm index.php
location ~\.php$ {
    try_files $uri =404;
    fastcgi_pass unix:/dev/shm/php-cgi.sock;
    include fastcgi.conf;
}
service nginx reload

你可能还想知道这里使用的unix domain socket连接套接字/dev/shm/php-cgi.sock(很多教程使用路径/tmp,而路径/dev/shm是个tmpfs,速度比磁盘快得多)——Nginx 中 fastcgi_pass 监听端口 unix socket和tcp socket差别

完成上述操作之后,Nginx+PHP平台就搭建完成。

基于3号虚拟机,克隆出4、5号虚拟机,注意配置IP地址和防火墙,这里的4、5号服务器不需要直接被外部访问,因此可以更改防火墙规则,实现只允许1号负载均衡服务器的IP地址可访问:

vi /etc/sysconfig/network-scripts/ifcfg-ens33 # 改IP
iptables --list -n --line-numbers# 查看规则
iptables -R INPUT 1 -s192.168.177.1 -p tcp --dport 80 -j ACCEPT
service iptables save

关于iptables,访问本机:在 INPUT 链上做过滤;本机访问外部:在 OUTPUT 链上做过滤;通过本机访问其他主机 : 在 FORWARD 链上做过滤。你可能需要补习iptables 教程

配置反向代理和负载均衡

经过前面的配置,4、5号服务器只能由1号服务器访问,下面在1号服务器中对Nginx进行配置以实现反向代理和负载均衡,编辑/usr/local/nginx/conf/nginx.conf

server {
    listen 80;
    server_name itshop.test www.itshop.test;
    location / {
        proxy_pass http://web_server;
        proxy_http_version 1.1;    # 后盾服务器使用HTTP1.1
        proxy_set_header Connection "";  # 清空客户端Connection消息头
        proxy_set_header Host $host;  # 传递Host头
        proxy_set_header X-Real-IP $remote_addr;  # 传递真实客户端IP
    }
}
upstream web_server{
    server 192.168.177.14;
    server 192.168.177.15;
    keepalive 32;  # 与后端服务器保持的长连接数
}

可以自己在/data/www下编写index.php:

<?php
echo phpinfo();
?>

在本机访问,可以看到REMOTE__ADDR为负载均衡机(1号机)地址:

itshop.test/index.php

上面利用X-Real-IP请求头传递了真实客户端的IP,为了后盾4、5号服务器将来自1号服务器的X-Real_IP请求头识别为客户端IP,还需要在4、5号服务器的server块中配置:

real_ip_header X-Real-IP;
set_real_ip_from 192.168.177.11;  # 只从来自指定IP的请求中获取X-Real_IP

别忘了:service nginx reload

itshop.test/index.php

【其实,部署着部署着,我就觉得太繁琐了,还不如上docker,但吐槽归吐槽,我们继续完成后续的内容】

LNMP 分布式集群的部署实践 系列文章:


dfface 的版权声明:所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处,严禁商业用途!