一、LNMP架构概述

LNMP是目前主流的企业网站部署平台,由四大核心组件构成,各司其职协同工作:

  • L(Linux):操作系统,提供底层运行环境
  • N(Nginx):网站服务软件,处理静态资源、反向代理、负载均衡
  • M(MySQL/MariaDB):关系型数据库,存储网站业务数据
  • P(PHP/Python):网站开发语言,实现动态业务逻辑处理

二、LNMP环境完整部署(实操代码+步骤)

2.1 编译安装Nginx(1.22.1版本)

2.1.1 准备工作

nginx-1.22.1.tar.gz源码包上传至虚拟机web1/root目录,执行以下命令:

# 安装编译依赖包
[root@web1 ~]# dnf -y install gcc pcre-devel openssl-devel make
# 创建nginx运行用户(无登录权限)
[root@web1 ~]# useradd nginx
# 解压源码包
[root@web1 ~]# tar -xf /root/nginx-1.22.1.tar.gz
# 进入源码目录
[root@web1 ~]# cd nginx-1.22.1

pcre-devel使nginx可以支持正则

2.1.2 编译配置+安装
# 初始化编译参数
[root@web1 nginx-1.22.1]# ./configure \
> --prefix=/usr/local/nginx \
> --user=nginx \
> --group=nginx \
> --with-http_ssl_module
# 编译并安装
[root@web1 nginx-1.22.1]# make && make install
# 验证安装(目录存在即成功)
[root@web1 nginx-1.22.1]# ls /usr/local/nginx

2.2 安装MariaDB数据库

  • mariadb-devel:是mariadb服务的扩展依赖包
# 安装数据库服务端+客户端
[root@web1 ~]# dnf -y install mariadb-server mariadb
# 安装数据库扩展依赖包
[root@web1 ~]# dnf -y install mariadb-devel

2.3 安装PHP环境(含FPM+数据库扩展)

  • 安装php、php-fpm、php-mysqlnd
    • php:php语言的解释器,用于在服务器执行php代码
    • php-fpm:php进程的管理程序,负责接收Nginx转发的php请求
    • php-mysqlnd:php连接数据库的扩展功能包,使php可以连接数据库
# 安装PHP相关组件
[root@web1 ~]# dnf -y install php php-fpm php-mysqlnd
# 验证安装
[root@web1 ~]# rpm -q php php-fpm php-mysqlnd

2.4 启动服务并设置开机自启

  • nginx端口号:80
  • mariadb端口号:3306
  • php-fpm端口号:9000(需要手动配置,后续配置)
# 启动Nginx
[root@web1 ~]# /usr/local/nginx/sbin/nginx
# 启动MariaDB并设置开机自启
[root@web1 ~]# systemctl enable mariadb --now

# 验证Nginx端口
[root@web1 ~]# ss -nutlp | grep :80
# 验证MariaDB端口
[root@web1 ~]# ss -nutlp | grep :3306

三、Nginx+FastCGI:动静分离核心原理与详细配置步骤

  • FastCGI通信协议PHP-FPM 是实现了 FastCGI 协议的进程管理器,用来处理php动态页面,管理进程池
    • Nginx 通过 FastCGI 协议 和 PHP-FPM 进程通信,转发 PHP 请求、接收执行结果。

3.1 FastCGI工作原理

  • FastCGI是Nginx服务和PHP通信的标准协议,需要安装php-fpm软件才能支持请添加图片描述
  • Nginx本身不能解析 PHP 代码,只处理静态资源
  • 遇到 PHP 动态请求时,Nginx通过FastCGI 协议把请求转发给 php-fpm
  • php-fpm负责管理php进程池,将请求调度至空闲的php进程执行php脚本(一个fpm可以拥有多个php进程,每个进程都可以处理用户请求);
  • php脚本在运行的时候连接MariaDB/MySQL数据库(如需)完成数据增删改查;
  • 处理完的结果php-fpm原路通过FastCGI协议返回给 Nginx,再由 Nginx 返回给浏览器。
  • 此流程图也是Nginx动静分离的工作原理图

请添加图片描述

  • 静态页面:写死内容,不用后端处理,不用编译,不用执行,浏览器直接渲染显示
  • 动态页面:是由编程语言实现的,核心是后端实时运算、查数据库、拼接内容,是代码的运行结果
  • 真实生产环境中都是动静结合的

nginx本身只支持静态页面,但可以联动php

动静分离:让Nginx专注于处理静态页面,动态的请求交给后端的其他服务处理,从而提升站点的性能

3.1.1 FastCGI简介及优缺点
FastCGI简介
  • FastCGI是Nginx服务和php-fpm通信的标准协议
  • 基于 FastCGI 协议,几乎所有主流编程语言都可以实现对应的处理程序,如 PHP、Python、Perl、Java、C/C++、Ruby 等。
优点
  • 基于标准协议,支持PHP、Python、Java等多种主流语言;
  • 可以实现Nginx动静分离,提升网站访问效率。
缺点(了解)
  • 内存消耗大
    • 采用多进程模型处理请求,每个 PHP 进程都是独立运行的,会占用固定的内存资源。
    • 通常,单个 PHP 解释器进程的内存占用在 7MB ~ 25MB 之间;
    • 高并发场景下,如果进程池配置了 50~100 个 PHP 进程,总内存占用会非常可观。
  • 典型场景示例(Nginx + PHP-FPM 架构):
    • 10 个 Nginx 进程,每个约占 15MB 内存,总消耗约:10 × 15MB = 150MB
    • 64 个 PHP-FPM 进程,每个约占 20MB 内存,总消耗约:64 × 20MB = 1280MB
    • 在3万并发连接的压力下,需要更多的常驻进程,这种内存占用是架构本身的特性决定的。

3.2 动静分离详细配置步骤:

  • php-fpm的配置文件可以定义两种连接方式
    • 基于网络协议栈的通信方式:Nginx和php-fpm通过9000端口进行数据交换
    • 基于本地文件的进程间通信方式:Nginx和php-fpm 通过 /run/php-fpm/www.sock 文件进行数据交换(就是将请求写入此文件,fpm通过读取文件实现通讯,这种方法不适合跨主机)

步骤一:配置PHP-FPM监听9000端口

  • php-fpm配置文件路径为: vim /etc/php-fpm.d/www.conf

PHP-FPM默认监听本地sock文件,需修改为9000端口监听并重启服务:

[root@web1 ~]# vim /etc/php-fpm.d/www.conf          #修改php-fpm配置文件
...此处省略1万字,大约第37行(有的人不是37行,但是基本大差不差),注释掉,并在其下方增加如下内容...

;listen = /run/php-fpm/www.sock                     #把第37行前方加上;注释
listen=127.0.0.1:9000  #本机127.0.0.1监听9000端口。这里的意思是动态请求转给哪台主机的9000端口,因为nginx和fpm在同一主机,所以写本机监听9000
...此处省略1万字...
[root@web1 ~]# systemctl restart php-fpm            #重新启动服务
[root@web1 ~]# ss  -nutlp  | grep   :9000           #查看9000端口

此步骤改动仅两处:
一是将listen = /run/php-fpm/www.sock 前加上;进行注释
二是在前一条注释下增加新的监听地址和端口listen=127.0.0.1:9000

注意: 如果是跨主机,也就是当 web 端(nginx)和后端的程序(PHP-是存放后端程序的主机的 IP 地址,就要使用能和别的主机通讯的本机ip。即:
FastCGI 配置在 Web 端(nginx),PHP 程序在哪台主机,fastcgi_pass 就指向哪台主机的 IP 地址。

步骤二:修改Nginx配置支持PHP动态请求

  • 修改nginx配置文件,是Nginx支持php动态请求
  • 将/usr/local/nginx/conf/nginx.conf的第66行-72行去掉注释,并配置

注意!此段内容不必手敲,nginx.conf 源文件之中自带,去掉前面的#号注释稍加修改即可。此处修改内容仅两处:

  • 一是将一段进行注释(示例中已详细说明)
  • 二是将include 后面的fastcgi改成conf结尾:fastcgi.conf
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf  #修改nginx配置文件
...此处省略1万字,下方为nginx.conf中的模板(大约第66行左右)代码...
 location ~ \.php$ {                        #~ \.php$ 是正则表达式,用于匹配php页面。此处的作用是判断是否为php页面
            root           html;
            fastcgi_pass   127.0.0.1:9000;  #动态请求转发给本地的9000端口即php-fpm服务
            fastcgi_index  index.php;
         #  fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;  #注释此行
            include        fastcgi.conf;  #调用配置,加载FastCGI参数文件,一定是.conf文件
        } 
...此处省略1万字...
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload  #重新加载配置文件
[root@web1 ~]# ss -nutlp  | grep :80                  #查看nginx端口号,正常

流程解析:
当用户访问 以 .php 结尾 的地址时:

  1. Nginx 先在 root html(即 /usr/local/nginx/html)目录下查找对应的 .php 文件
  2. 找不到 → 直接报错
  3. 找到 → 把请求转发给 127.0.0.1:9000(php-fpm 进程)
  4. php-fpm 调用 PHP 引擎执行这个 PHP 文件
  5. 执行结果返回给 Nginx
  6. Nginx 再返回给用户

location就是如果的意思,/ 匹配了你的访问地址,代表此虚拟主机的IP地址或者域名。
location / {} 的意思是如果你访问我的ip,我就从{}里的配置给你寻找

所以location语句的作用是匹配用户访问的地址

因此location ~ .php$ { } 意思就是匹配以.php结尾的页面。

而当同一个server同时包含 location ~ .php$ { } (动态配置)和 location \ { }
(静态配置),那么会优先匹配 location ~ .php$ { }

如果将nginx和php-fpm分别做到两台主机(也就是动,静分离到两个主机),应该这样配置:
机器 A(Nginx 所在机器)的 /usr/local/nginx/conf/nginx.conffastcgi_pass 192.168.8.100:9000;
机器 B(php-fpm 所在机器:192.168.8.100)的 /etc/php-fpm.d/www.conflisten=192.168.8.100:9000

3.5 LNMP环境测试

  • 编写php测试页面,客户端访问测试、Windows访问测试
  • 访问地址:http://192.168.8.100/test.php
3.5.1 测试PHP解析
[root@web1 ~]# vim /usr/local/nginx/html/test.php    #编写php测试页面
<?php
$i=33;
echo $i;
?>
[root@web1 ~]# curl 192.168.8.100/test.php           #本机访问测试,可以看到33
3.5.2 测试PHP连接MariaDB
  • 编写php测试页面,将测试mysql.php测试脚本上传至虚拟机的/root
  • 将测试页面拷贝至/usr/local/nginx/html目录
# 上传mysql.php测试脚本到/root,拷贝至Nginx网页目录
[root@web1 ~]# cp /root/mysql.php /usr/local/nginx/html/
# 查看测试文件
[root@web1 ~]# cat /usr/local/nginx/html/mysql.php
# 本机访问测试
[root@web1 ~]# curl 192.168.8.100/mysql.php
# 浏览器访问:http://192.168.8.100/mysql.php,显示数据库信息即连接成功

mysql.php页面代码为:

<?php
$mysqli = new mysqli('localhost', 'root', '', 'mysql');
if (mysqli_connect_errno()){
        die('Unable to connect!'). mysqli_connect_error();
}
$sql = "select * from user";
$result = $mysqli->query($sql);
while($row = $result->fetch_array()){
        printf("Host:%s", $row[0]);
        printf("</br>");
        printf("Name:%s", $row[1]);
        printf("</br>");
}
?>

四、Nginx高级技术:地址重写/地址跳转(rewrite)

4.1 地址重写概述

  • 获得一个来访的URL请求,然后改写成服务器可以处理的另一个URL的过程
  • 地址重写的好处
    • 缩短URL,隐藏实际路径,提高安全性
    • 易于用户记忆和键入
    • 易于被搜索引擎搜录
  • rewrite基本语法(记住一个简单的即可)
    • rewrite regex replacement [flag]
      • regex就是正则
    • rewrite 旧地址 新地址 [标记]

目前很多大厂的网站都使用了这个技术。
实例:输入:www.360buy.com 实则跳转到:www.jd.com

4.2 3.4 rewrite标记语法补充

  • rewrite 旧地址 新地址 [标记]
    • last(了解):停止执行其他重写规则,重新匹配 location
    • break(了解):停止执行其他的重写规则,完成本次请求
    • redirect:302 临时重定向,地址栏改变,爬虫不更新 URI
    • permanent:301 永久重定向,地址栏改变,爬虫更新 URI

4.3 实战案例1:单页面跳转(a.html→b.html)

4.3.1 基础跳转(模糊匹配)
  • 当用户访问:192.168.8.100/a.html --跳转至–> 192.168.8.100/b.html
  • 使用Windows访问测试,查看效果
# 创建测试页面
[root@web1 ~]# echo AAA > /usr/local/nginx/html/a.html
[root@web1 ~]# echo BBB > /usr/local/nginx/html/b.html

# 配置基础跳转
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
    root   html;
    index  index.html index.htm;
    rewrite /a.html  /b.html; #实现页面跳转
    #这里的 / 指代网页根目录的根或者网络地址,即网页根目录或者本机ip
}

# 重载配置
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload
# 测试跳转
[root@web1 ~]# curl 192.168.8.100/a.html
# 输出BBB,但a.htmlabc也会跳转(匹配不严谨)

注意:配置了rewrite之后,会优先走rewrit,然后走正常的页面查找顺序(root,index)

4.3.2 页面跳转优化:正则精准匹配
  • 目前访问192.168.8.100/a.htmlabc也会跳转192.168.8.100/b.html
  • 目前对于URL的匹配是包含关键字a.html即可跳转,这样不严谨
  • 可以使用正则表达式优化配置
# 修改配置(精准匹配a.html)
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
    root   html;
    index  index.html index.htm;
    rewrite ^/a\.html$  /b.html;
}

# 重载配置
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload
# 测试
[root@web1 ~]# curl 192.168.8.100/a.html      # 跳转成功
[root@web1 ~]# curl 192.168.8.100/a.htmlabc   # 不跳转
4.3.3 浏览器地址栏同步跳转(redirect)
  • 目前Windows浏览器访问192.168.8.100/a.html页面内容可以跳转
  • 但是URL中的地址不会跳转,可以增加redirect标记重定向
  • Windows浏览器重新访问,查看URL地址栏会跟随跳转
# 配置临时重定向
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
    root   html;
    index  index.html index.htm;
    rewrite ^/a\.html$  /b.html    redirect; #浏览器顶部导航栏一同跳转
}

# 重载配置
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload
# 浏览器访问:http://192.168.8.100/a.html,地址栏自动变为b.html

同理,如果想要配置动态页面的rewrite,需要在location ~ .php$ { }之中进行配置即可。

4.4 实战案例2:跨站跳转

4.4.1 全站跳转(192.168.8.100→www.jxsedu.com)
  • 不同网站间的跳转:192.168.8.100 --跳转至–>www.jxsedu.com
  • Windows浏览器访问测试
# 配置全站跳转
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
    root   html;
    index  index.html index.htm;
    rewrite /   https://www.jxssedu.com;
}

# 重载配置
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload
4.4.2 子页面同步跳转(带路径)
  • 不同网站间的跳转:192.168.8.100 --跳转至–>https://www.jxssedu.com
  • 访问192.168.8.100/single/cloud跳转至https://www.jxssedu.com/single/cloud
  • Windows访问测试
# 配置子页面跳转
[root@web1 ~]# vim /usr/local/nginx/conf/nginx.conf
location / {
    root   html;
    index  index.html index.htm;
    rewrite /(.*)   https://www.jxssedu.com/$1;
    #使用正则表达式(.*)获取用户就地址中的子页面,跳转至新地址的相同子页面。$1表示前方(.*)保留的内容
}

# 重载配置
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s reload
# 访问192.168.8.100/single/cloud,跳转至对应子页面:www.jxssedu.com/single/cloud

五、systemd管理Nginx服务(编写unit文件)

5.1 systemd Unit文件概述

  • systemd使用systemcl管理服务会读取对应的文件,此文件就是服务的unit文件
  • 读取文件的目录(由高到低)
  1. /etc/systemd/system:(设置了开机自启的Unit文件)
    • 优先级最高,用户自定义服务(源码自建、自 己编写的 service 都放这),包含手动配置、设置开机自启的服务单元。
  2. /usr/lib/systemd/system:(所有已安装软件的Unit文件)
    • 系统默认服务目录,yum/apt 官方包自带的服务文件都在这里,软件默认自带单元文件存放处。
5.1.14.1 Unit语法格式

请添加图片描述

5.2 编写nginx.service文件

service文件为服务的启动说明文件(Unit文件),此文件记录了如何启动对应的服务
nginx现在没有nginx.service文件,所以使用systemctl命令无法启动nginx服务,因为systemctl不知道如何启动(源码包安装的软件都是这样)

  • 交代环境背景,可使用AI配合生成nginx.service文件,适当微调
  • 配置中不要出现中文
# 创建Nginx服务unit文件
[root@web1 ~]# vim /usr/lib/systemd/system/nginx.service
[Unit]
Description=The Nginx HTTP Server #描述信息
After=network.target remote-fs.target nss-lookup.target   ##在网络程序,网络文件系统,域名解析等服务启动之后,再启动nginx

[Service]
Type=forking  #forking多进程类型服务
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID #kill给程序发送QUIT退出信号,关闭nginx

[Install]
WantedBy=multi-user.target

注意:

  1. service文件,用原生命令启动Nginx,进程为独立后台进程,不受systemd管控
  2. 后续编写并重载service文件,仅完成服务规则注册,不会自动接管已运行的旧进程
  3. 此时systemctl stop nginx依旧无效,只能使用kill或killall命令终止原有进程。
  4. 彻底杀掉旧进程后,重新执行systemctl start nginx拉起服务,进程正式交由systemd托管,此后可正常使用systemctl全套命令管理。

5.3 生效配置并管理服务

# 停止原有Nginx进程
[root@web1 ~]# /usr/local/nginx/sbin/nginx -s stop
# 重载systemd配置
[root@web1 ~]# systemctl daemon-reload
#此命令用于强制 systemd 重新扫描所有服务配置文件,让新增 / 修改的.service 服务文件配置生效

# 启动Nginx
[root@web1 ~]# systemctl start nginx
# 设置开机自启
[root@web1 ~]# systemctl enable nginx
# 验证端口
[root@web1 ~]# ss -nutlp | grep :80
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐