NGINX的安装和配置(Linux环境)

目录

  • [NGINX 安装方式](#NGINX 安装方式)
    • [1、 离线编译安装](#1、 离线编译安装)
    • [2、 在线仓库安装](#2、 在线仓库安装)
  • [NGINX 常用命令](#NGINX 常用命令)
  • [NGINX 配置文件](#NGINX 配置文件)
  • [NGINX 全局配置](#NGINX 全局配置)
  • [NGINX 配置MIME](#NGINX 配置MIME)
    • [1、MIME 标准](#1、MIME 标准)
    • [2、types 配置块](#2、types 配置块)
    • [3、default_type 指令](#3、default_type 指令)
  • [NGINX 日志管理](#NGINX 日志管理)
  • [NGINX 内置变量](#NGINX 内置变量)
  • [NGINX 配置 Web](#NGINX 配置 Web)
  • [NGINX 实现重写](#NGINX 实现重写)
    • 1、重写的概念
    • [2、rewrite 指令](#2、rewrite 指令)
    • [3、try_file 指令](#3、try_file 指令)
    • [4、rewrite_log 指令](#4、rewrite_log 指令)
    • [5、try_file vs rewrite](#5、try_file vs rewrite)
  • [NGINX 反向代理](#NGINX 反向代理)
  • [NGINX 负载均衡](#NGINX 负载均衡)
    • 1、负载均衡的策略
    • [2、upstream 指令块](#2、upstream 指令块)
    • [3、server 指令](#3、server 指令)
    • [4、NGINX 四层负载均衡](#4、NGINX 四层负载均衡)
    • [5、NGINX 七层负载均衡](#5、NGINX 七层负载均衡)
  • [NGINX 优化策略](#NGINX 优化策略)
    • 1、服务配置优化
    • 2、设置缓存策略
      • [(1)Cache-Control 响应字段](#(1)Cache-Control 响应字段)
      • [(2)Expires 响应字段](#(2)Expires 响应字段)
      • [(3)Etag 响应字段](#(3)Etag 响应字段)
      • [(4)expires 指令](#(4)expires 指令)
    • [3、NGINX 服务器优化](#3、NGINX 服务器优化)
  • [NGINX 实现 LNMP](#NGINX 实现 LNMP)
    • 1、LNMP数据流向
    • [2、CGI/FastCGI 协议](#2、CGI/FastCGI 协议)
    • [3、PHP-FPM 组件](#3、PHP-FPM 组件)
  • [NGINX 配置LNMP](#NGINX 配置LNMP)
    • [1、PHP 安装配置](#1、PHP 安装配置)
    • [2、PHP-FPM 安装配置](#2、PHP-FPM 安装配置)
    • [3、NGINX 安装和配置](#3、NGINX 安装和配置)
      • [(1)fastcgi_pass 指令](#(1)fastcgi_pass 指令)
      • (2)fastcgi_split_path_info
      • [(3)fastcgi_index 指令](#(3)fastcgi_index 指令)
      • [(4)fastcgi_param 指令](#(4)fastcgi_param 指令)
      • [(5)scgi_param 指令](#(5)scgi_param 指令)

NGINX 安装方式

1、 离线编译安装

文档链接:https://nginx.org/en/docs/configure.html

2、 在线仓库安装

文档链接:https://nginx.org/en/linux_packages.html

NGINX 常用命令

1、进程管理命令

bash 复制代码
# 启动nginx,默认前台启动(默认使用的配置文件是由 NGINX 在编译时设置的 默认配置文件路径)
sudo nginx

# 启动nginx指定配置文件,否则使用编译时指定的配置文件
sudo nginx -c nginx.conf

# 停止nginx
sudo nginx -s stop

# 快速停止nginx
sudo nginx -s quit

# 平滑重启nginx(不中断现有连接 的情况下重新加载配置文件或重启服务,从而实现配置变更的生效。)
sudo nginx -s reload

2、信息查看命令

bash 复制代码
# 查看nginx版本
nginx -v

# 查看nginx详细版本信息(包括编译参数):
nginx -V(大写)

# 检查nginx检查配置文件语法是否正确
nginx -t

NGINX 配置文件

1、进程使用的配置

启动 NGINX 时,如果没有指定配置文件,则默认使用的是编译NGINX源码时,通过 --conf-path 参数指定的配置文件,如果需要指定配置文件,需要使用 NGINX 的的 -c 选项进行指定配置文件;

bash 复制代码
/usr/sbin/nginx -c /etc/nginx/nginx.conf

2、配置文件格式

  • 单个指令:每行由指令和参数组成,以分号;结尾。

  • 块结构:使用大括号 {} 定义一个配置块。

  • 注释:使用#开始,表示单行注释;

  • 文件包含:通过 include 指令引入其他配置文件。

3、配置文件层级

NGINX 的配置文件可以分为两大类,一类必须存在,影响的是整个 NGINX 进程,一类是按照功能的需要添加;

  • 必须存在的配置:属于全局配置指令,对整个NGINX服务生效,如果缺少某些关键项,则Nginx 无法正常启动。

  • 按需添加的配置:根据功能需求决定是否添加,用来扩展 Nginx 的功能,优化性能或支持特定场景的应用。

NGINX 全局配置

1、全局配置常用指令

NGINX 全局配置指令对整个 NGINX 服务生效,如果缺少某些关键项,则 NGINX 无法正常启动。常用的全局配置指令有以下指令:

  • user:指定运行NGINX工作进程的用户,该用户需要对NGINX配置文件中指定的路径或文件要有读写权限;
  • pid:指定NGINX正常运行中,存在NGINX进程的PID的文件路径; error_log:定义全局错误日志文件的位置和日志级别。
  • worker_processes:定义NGINX工作进程数量(设置为 auto 时根据 CPU 核心数自动调整)
  • include:引入其他配置文件,便于分模块管理。

例如:

bash 复制代码
# user:执行运行nginx进程的用户
user  nginx;

# worker_processes:指定worker进程数量,auto表示会根据cpu的核心数来指定nginx的worker进程数量
worker_processes  auto;

# error_log 指定nginx的错误日志存放路径和日志级别
error_log  /var/log/nginx/error.log notice;

# pid 指定nginx的pid文件存放路径
pid        /var/run/nginx.pid;

# include 包含指定的子配置文件,通过引入子配置文件的方式来进行模块化配置
include /etc/nginx/conf.d/*.conf;

2、连接相关配置

NGINX 连接相关的配置是通过event块实现,event 块如果没有在配置文件中指定,NGINX使用的是默认的连接配置。

例如:

bash 复制代码
events {
  worker_connections  1024;  # 指定一个worker进程可以处理多少个连接
}

NGINX 配置MIME

1、MIME 标准

最初,电子邮件系统最早仅支持 ASCII 文本,无法处理其他字符集或多媒体内容(如图像、音频、视频、非英语字符等),后面发布了一个名为MIME(Multipurpose Internet Mail Extensions)的标准,这个标准通过在邮件头部增加一些字段,如 Content-Type 和 Content-Transfer-Encoding,指定邮件的编码方式和内容类型,使得邮件能够支持多种格式和字符集,解决了这个问题。

随着时间发展, MIME 被应用于 HTTP 协议 中,以便 Web 服务器能够告诉客户端(浏览器)服务器返回的数据是什么类型。这通常通过 Content-Type 响应头来实现。

2、types 配置块

服务端通过 types 配置块来指定特定后缀的文件指定的MIME类型。

types 语法格式:

bash 复制代码
types {
   主类型/次要类型  对应的后缀;
}

例如:

bash 复制代码
types {
    text/html                                        html htm shtml;
    text/css                                         css;
    text/xml                                         xml;
    image/gif                                        gif;
    image/jpeg                                       jpeg jpg;
    application/javascript                           js;
}

3、default_type 指令

该指令用于指定默认的MIME类型,也就是返回给客户端某个数据后,如果没有从types指令块中匹配到对应的文件类型,就返回这个默认的文件类型;

default_type 语法格式default_type 主类型/次要类型;

例如:

bash 复制代码
default_type  application/octet-stream;

NGINX 日志管理

NGINX 支持错误日志和访问日志两种日志类型:

  • 访问日志:记录所有经过 NGINX 处理的请求信息。可以指定日志格式,需要结合nginx的变量使用;

  • 错误日志:记录 NGINX 运行过程中遇到的各种错误信息,不可以指定日志格式,可以指定从那种级别的日志开始记录;

1、访问日志管理

指定日志内容: log_format <name> '<format>';

  • <name>:自定义的格式名称
  • <format>:定义日志格式的字符串,包含一系列的变量,用于记录请求的信息。

配置访问日志access_log /path/log_name <name>

  • /path/log_name:访问日志的存放路径,需要运行 nginx 的用户具有读写权限
  • <name>:使用哪种格式的访问日志格式;

2、错误日志管理

配置错误日志 ::error_log /path/log_name [ debug | info | notice | warn | error | crit

  • 日志级别可以省略,默认是error级别

错误日志级别:

  • debug: 需要在调试过程中输出的信息,但发布后是不需要的(当然发布后,也是看不到的)
  • info:需要持续输出的信息(无论调试还是发布状态)
  • notice: 不影响正常功能,需要注意的消息
  • warn:可能影响系统功能,但需提醒用户的重要事件(不严重)
  • error: 错误信息(较严重)
  • crit:比error还要严重的报错信息,这个crit表示这个报错信息已经很严重了

NGINX 内置变量

通过NGINX的内置变量,可以获取某个客户端请求的相关信息,以及服务端的相关信息。

1、客户端信息

  • $remote_addr:获取某次请求客户端的IP地址,该地址是NGINX直接从网络连接中提取的,来源于 TCP 连接的 IP 地址。
  • $host:基于请求头中的 Host 字段获取,Host字段的值又是从客户端的URL中获取的,可以是IP地址,也可以是域名;例如:客户端的url是 http://10.0.28.8/index.html ,则 请求头中Host字段的指就是 10.0.28.8;
  • $remote_user:获取客户端在 HTTP 基本认证(Basic Authentication)中提供的用户名。是从 HTTP 请求头中的 Authorization 字段中获取的
  • $remote_port:获取客户端的源端口号,是通过 TCP 连接的源端口获取的
  • $request:客户端发出的 HTTP 请求行,是直接来自客户端发送的 HTTP 请求。例如客户端的请求是 http://10.0.28.8/index.html ,则$request值就是 http://10.0.28.8/index.html
  • $request_method:获取客户端发起HTTP请求时的请求方法。也是直接从HTTP请求行中获取;
  • $request_uri:客户端请求的完整 URI,包括查询字符串(如果有)。是从客户端请求的 Request URI 中获取(即,去除域名部分后的完整路径和查询字符串)。
  • $uri:请求的标准化路径部分,不包括查询字符串,从 $request_uri 中提取,并经过标准化处理,如去除请求中的域名部分。
  • $args:表示 URI 中的查询字符串部分(即 URL 中 ? 后的部分,包含 & 和 = post请求没有查询字符串)。GET请求才有;
  • $is_args:表示是否存在查询字符串,若存在,则值为 ?,否则为空字符串。例如:http://10.0.28.8/index.html ,没有查询字符串,所以该变量为空;
  • $query_string:表示请求的查询字符串部分,包含查询符号 ?http://10.0.28.8/index.html?name=bob,则该变量的值为`?name=bob`
  • $document_uri:表示请求的 URI,不包括查询字符串。多数情况下,它和 $uri 相同。例如http://10.0.28.6/LocationDeviceManage/index.php/home/Index/getEH100602SysInfo,则该变量的值为/LocationDeviceManage/index.php/home/Index/getEH100602SysInfo

2、服务端信息

  • $document_root:表示服务器配置中定义的文档根目录,由NGINX中root指令指定的值决定;

  • $server_name: 获取服务端主机名,由NGINX中的server_name指令决定;

  • $document_root:文档根目录,获取的是NGINX中root指令指定的路径。

  • $status :获取服务端的响应状态,是在 NGINX 响应请求后,从服务器生成的响应头中提取的 HTTP 状态码。例如,200、404、500 等。

  • $sent_http_<header>:获取服务端响应头中,某个某个特定字段的值。变量名是 sent_http_ 后接 HTTP 头字段的名称,字段名会自动转为小写并且替换掉任何 -(短横线)为 _(下划线)

  • server_addr:获取的是服务端的IP地址

  • server_port:获取的是服务端的端口号

NGINX 配置 Web

NGINX 的两大作用,一个是配置为 Web 服务端,另外一个就是实现反向代理、负载均衡等;在 NGINX 中,Web 服务端的相关配置都是在 http 配置块里面完成的;

1、http 配置块

http配置专门用于配置与 Web 服务相关的内容,直接放在 http 块里面的指定属于全局配置指令,对所有的虚拟主机都生效;

http配置块常用指令

  • keepalive_timeout:配置 HTTP 长连接的超时时间。处理完某个 http 请求后,如果在该时间内没有新的请求,连接将被关闭。
  • client_max_body_size:客户端上传文件的最大大小;

2、service 配置块

在配置 web 服务端的时候,server 配置块必须存在,用于指定某个虚拟主机,告诉 NGINX 如何处理特定的请求。

server 配置块常用指令:

  • listen:用于指定该虚拟主机监听的端口,如果只写端口号,监听的是 TCP 端口·;
  • server:指定虚拟服务器的主机名,可选
  • root:指定该虚拟服务器的根目录 index:指定虚拟服务器的默认访问页面
  • access_log:指定该虚拟服务器的访问日志路径
  • error_log:指定该虚拟服务器的错误日志路径

3、location 配置块

location 配置块用于根据客户端请求的某个URI来指定某种匹配规则,如果客户端请求某个资源的UEI满足某个location规则,则会执行该location 配置快中的相关指令;

location 块语法格式:

bash 复制代码
location [匹配符] 路径 {
	# 相关指令
}

location 块的四种优先级:

  • 精确匹配:匹配符是 = ,需要URI完全和指定path一致才会被匹配到,优先级最高;
  • 前缀匹配:匹配符是 ^~ ,将请求的URI 路径与 location 块中指定的前缀进行匹配,这种方式明确告知 NGINX 优先使用该前缀匹配规则,而不会再进一步匹配正则规则。优先级次高;
  • 正则匹配 :匹配符是~,优先级第三,这种方式支持正则和扩展正则,会将 URI 和指定的正则表达式进行匹配;
  • 普通匹配:没有匹配符,普通匹配又叫做普通前缀匹配,基于路径前缀来对某个URI进行匹配,优先级最低;

4、服务端跨域配置

(1)什么是跨域问题


跨域产生的原因

跨域问题是由于浏览器的安全策略引起的,该策略称为 同源策略。同源策略要求,当客户端(如浏览器)发起 HTTP 请求时,请求的目标 URL 必须与当前页面的 URL 保持一致。如果请求的 URL 与当前页面的 URL 中的 协议、域名 或 端口 中任意一个不一致,浏览器就会认为这是一个跨域请求,从而阻止该请求的执行。

例如:浏览器直接访问的是:http://10.0.0.24:80/index.html,假设此时 index.html 中的 js 代码会去访问 http://10.0.0.24:8000 的内容;因为这种客户端请求的内容(假设请求的页面里面的 js 会发起一个新请求)里面会再发起一个请求时,新请求的 URL 中的协议、域名和端口任意一个不一致,浏览器就认为这是也给跨域请求,从而阻止这个请求;


浏览器同源策略

同源策略指的是浏览器发起一个请求后,后面基于浏览器这个请求发起的请求,要求这些请求的协议、域名和端口必须和浏览器发起的初始请求一致,否则 浏览器就会视为跨域请求。

同源策略的目的是为了防止潜在的安全风险,避免一个网站的恶意脚本访问另一个网站的资源。当跨域请求发生时,浏览器会阻止该请求并视其为不安全。


两种请求方式对比

浏览器独立请求: 浏览器分别发起两个不同的请求(例如先请求 http://siteA.com,然后请求 http://siteB.com),这些请求是独立的,即使它们分别来自不同的源(协议、域名或端口不同),浏览器也不会认为是跨域请求。因为每次请求都是一个新的、独立的操作,浏览器不会做跨域限制。

浏览器嵌套请求: 浏览器在一次请求中发起了第二次请求(例如通过当前请求中的 JavaScript 发起一个新的 HTTP 请求),那么第二个请求的 URL 如果与第一次请求的协议、域名或端口不一致,就会被认为是跨域请求。


跨域请求的流程

  1. 发起预检请求:如果客户端发起的 http 请求不是一个简单的请求,或者携带了自定义的请求头,那么浏览器会首先发送一个 OPTIONS 请求,以询问目标服务器是否允许跨域请求。
  2. 服务器响应:如果服务器允许跨域请求,响应中会包含相应的 CORS(跨域资源共享)头部信息。浏览器根据这些头部信息判断请求是否被允许。如果允许,浏览器将继续发送实际的跨域请求;如果不允许,浏览器将阻止该请求。

简单请求的概念

客户段像服务端发起HTTP请求时,需要满足以下条件才算是一个简单的HTTP请求:

  • 请求方法:需要是 GET、POST 或 HEAD,像 PUT、DELETE 就不满足要求;
  • 请求头:必须是浏览器自动设置的标准头部,任何自定义的请求不满足要求;
  • 请求凭证:发起请求时不能携带凭据(如 cookies、HTTP 认证信息等),否则就不是简单请求;
  • Content-Type:需要是简单类型之一,例如:text/plain。application/json不是简单类型;

(2)解决跨域问题

跨域问题需要在 在服务器端配置相应的响应头信息,这样客户端发起请求的时候,响应头里面会携带对应的响应字段,从而让浏览器判断是否允许跨域;

常用的响应头:

  • Access-Control-Allow-Origin:指定允许哪些客户端源(即协议、域名、端口)可以跨域访问服务器资源。如果服务器响应头中 Access-Control-Allow-Origin 与浏览器请求中的 Origin 匹配,浏览器就允许跨域请求,否则就会被阻止。客户端源就是客户端第一次发起请求的协议、域名和端口。
  • Access-Control-Allow-Methods:指定允许哪些请求进行跨域,默认只允许 GET 和 POST 方法的请求跨域处理;
  • Access-Control-Allow-Headers:指定允许哪些非简单的请求头跨域处理,默认只允许浏览器自动设置的标准头部这种请求跨域;
  • Access-Control-Allow-Credentials:用于设置是否启用可以携带凭据进行跨域,默认不允许携带凭据的请求跨域;
  • Access-Control-Max-Age:用于再指定的时间内,如果浏览器再次需要发送一个相同的跨域请求,它可以重用之前缓存的预检请求结果,而无需再次发送OPTIONS预检请求。

(3)add_header 指令

NGINX 中提供了一个名为add_header 的指令,可以通过这个指令来向响应头中添加自定义的 HTTP 头部信息。

add_header 基本语法add_header <header-name> <header-value> [always];

  • <header-name>:指定要添加的头部名称,例如 Content-Type。
  • <header-value>:指定头部的值,可以是固定值,也可以使用变量。
  • always:如果不加这个选项,则只有当响应状态码为 2xx(成功)或 3xx(重定向)时,头部才会被添加。加了的话,所有响应都会强制添加这个头部,一般不用加;

例如:NGINX配置跨域策略

bash 复制代码
location / {
  add_header Access-Control-Allow-Origin *;
  add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, DELETE"";
  add_header Access-Control-Allow-Headers "Authorization,DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, Accept-Language, Origin, Accept-Encoding"
  add_header  Access-Control-Allow-Credentials  true ;
  Access-Control-Max-Age  120s
}

5、解决 405 响应错误

(1)err_page 指令

在NGINX中,如果使用POST方法来请求静态资源,则会返回405错误,此时可以通过 error_page指令来进行设置。通过该指令,可以让客户端请求服务端的某个资源时,如果服务端响应了某个状态码,则将这个状态码重写为指定的状态码,然后然会指定URI的内容给客户端。

err_page 指令格式error_page code [code ...] [=code] uri;

  • code:指定需要处理的 HTTP 错误码,可以是单个错误码,也可以是多个错误码。
  • =code:可选,表示错误页面重定向的 HTTP 状态码。
  • uri:自定义错误页面的路径,可以是静态文件的路径,也可以是内部重定向的 URI。

NGINX 实现重写

1、重写的概念

重写操作是指请求到达Web服务端后,请求还没传递给后端服务器处理的时候,就先通过对应的规则来修改客户端请求的 URL(URI)来改变请求的路径或行为。

NGINX的重写功能是通过 ngx_http_rewrite_module 模块来实现的,这个模块在安装NGINX的时候就自动编译进去了的。所以可以直接使用这个模块提供的相关指令来实现重写操作。


NGINX 重写的流程:

  1. 客户端发起请求:客户端向服务端发起一个http请求;
  2. 匹配重写规则:请求到达服务端后,会根据请求的 URI、请求头、请求方法等条件,判断是否需要进行重写。
  3. 重新匹配资源:会使用修改后的 URI 来查找匹配的资源并进行处理。

2、rewrite 指令

rewrite 语法格式rewrite <regex> <replacement> [flag];

  • <regex-pattern>:用于匹配请求的 URI 的正则表达式,支持普通正则和扩展正则。
  • <replacement>:将匹配到的 URI 替换成新的路径。
  • [flag](可选):重写标志,决定重写的行为,如果省略不写,默认是last;

rewrite 四种标志位:
last

  • 标志作用:如果使用 rewrite 指令的时候,没有指定标志位,默认就是 last 标志位;rewrite 重写规则执行完成后,该 location 块中后续的指令也不会再执行了,而是直接跳出该 location 块,然后使用重写后的 URI 来匹配新的 location 块;
  • 使用场景:基于重写后的 URI 匹配其它 location 块进行处理。

break

  • 这个标志表示 rewrite 重写规则执行完后,不会继续执行当前 location 中的其它 rewrite 指令,但是会继续处理当前 location 块中的其他指令;不会使用重写后的 URI 来匹配新的 location 块;
  • 应用场景:当需要中止 location 中的其它 rewrite 规则,但继续处理当前 location 块的其它指令时使用。

redirect

  • 表示客户端会收到一个 302 临时重定向,并会使用重写后的 URI 进行请求。
  • 应用场景:用于临时重定向到新的 URL,通常用于用户请求某个页面时暂时重定向到其他页面。

permanent

  • 表示客户端会收到一个 302 临时重定向,并会使用重写后的 URI 进行请求。
  • 应用场景:用于临时重定向到新的 URL,通常用于用户请求某个页面时暂时重定向到其他页面。

3、try_file 指令

try_file 指令主要用于按照顺序检查某个文件是否存在,如果所有检查的路径都不存在,就会返回最后一个指定的路径或内容。

try_file 指令语法格式try_files <file1> <file2> <file3> ... <fallback>;

  • <file1>, <file2>, <file3> 等:NGINX 会依次尝试这些文件或路径。如果某个文件存在且可访问,NGINX 会立即返回该文件的内容。

  • <fallback>:如果所有尝试的文件都不存在,try_files 会执行这个 fallback 操作(比如,返回 404 错误,或是跳转到其他 URI)。

4、rewrite_log 指令

通过 rewrite_log 指令可以用于开启 Nginx URL 重写(rewrite)的日志记录。开启后会记录 URL 重写过程中的详细调试信息,帮助调试和优化 URL 重写规则。

  • 开启:rewrite_log on;
  • 关闭:rewrite_log off;

rewrite_log 通常是放在 rewrite 或 try_files 等重写相关指令之前,与这些指令一起配置的,来记录重写过程的详细信息,当启用 rewrite_log 后,Nginx 会将每一次重写操作的详细信息记录到错误日志中。日志会显示匹配的规则、重写的目标URL、是否成功执行了重写等信息。所以需要将 Nginx 的错误日志级别 设置为 debug才能看到重写的记录信息;

5、try_file vs rewrite

相同点:

  • 两个指令都可以实现对用户请求的URI进行重写

不同点:

  • try_files 的最后一个参数并不是重新触发 location 匹配,而是直接处理该路径。如果最后一个路径不存在,如果最后一个路径不存在

  • rewrite 指令如果使用的是非break标志位,会将重写后的URI来重新匹配新的location块;

NGINX 反向代理

反向代理一般用于Web服务器中,指的是通过 Web 服务器作为中介,转发客户端的请求到一个或多个后端服务器上,并将后端服务器的响应返回给客户端。

1、proxy_pass 指令

NGINX的代理功能是通过一个名为 ngx_http_proxy_module 的内置模块实现;通过这个模块提供的相关指令就可以配置代理功能;

通过该模块提供的proxy_pass 指令,就可以将请求转发到其他服务器,不论是 TCP(四层)还是 HTTP(七层)。后端服务器处理完成后,会原封不动返还给真正的客户端;

proxy_pass 语法格式proxy_pass URL

  • 如果 proxy_pass 只包含协议(如 http 或 https)、主机和端口,而没有明确的路径部分,Nginx 会将原始请求的完整路径(包括请求路径和查询字符串)传递到后端服务器。
  • 如果 proxy_pass 中包含了路径,并且路径末尾有斜杠 /,Nginx 会删除原始请求路径的前缀(匹配的 location 块的路径部分),然后将剩余的部分与 proxy_pass 中的路径拼接起来,转发给后端服务器。

2、 proxy_set_header 指令

反向代理服务器接收到客户端的请求后,将请求转发给后端服务器之前,默认情况下,反向代理服务器会用自己的信息来构建发送给后端服务器的请求头,而不是客户端的原始请求头,反向代理服务器会基于自己的配置来构建请求头的原因是,因为它在代理客户端请求时通常会代表客户端。

代理服务器收到后端服务器的响应后,会原封不动将响应发送给客户端,所以需要代理服务器将请求转发给后端服务器的时候,就需要将对应的请求头设置为真正客户端的信息。


通过 proxy_set_header 这个指令就可以指定需要传递给后端服务器的请求头,确保原始客户端请求的信息能够正确传递。

proxy_set_header 语法格式proxy_set_header 请求头名称 请求头的值

  • 请求头名称;可以是任何有效的 HTTP 请求头字段名
  • 请求头的值:可以是固定的字符串、Nginx 内置的变量

NGINX中,配置反向代理时候,一般需要将这些请求头参数传递给后端服务器:

  • HOST:真正客户端的主机名,是从URL中获取的,可以是IP地址或者主机名;
  • X-Real-IP:记录客户端真实的IP地址
  • X-Forwarded-For:记录录经过代理服务器链的每个客户端 IP 地址,复杂代理才需要
  • X-Forwarded-Proto:记录客户端发起请求时的协议类型

例如:将指定请求转发到8000端口的虚拟服务器

bash 复制代码
# 指定后端服务器
proxy_set_header http://127.0.0.1:8000

# 客户端主机名
proxy_set_header Host $host;

# 传递客户端的真实 IP 地址
proxy_set_header X-Real-IP $remote_addr;

# 记录经过代理服务器链的每个客户端 IP 地址。(一般简单的代理可以省略这个配置)
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# 将客户端请求使用的协议(http 或 https)传递给后端服务器。
proxy_set_header X-Forwarded-Proto $scheme;

3、代理连接优化指令

  • proxy_connect_timeout:控制 NGINX 在向后端服务器发起连接时的 超时时间,即 NGINX 在尝试与后端服务器建立连接时,如果在该时间内未成功建立连接,就会终止尝试并返回错误。

  • proxy_timeout:指定 NGINX 和后端服务器之间的 请求/响应数据传输的超时时间。即从 NGINX 向后端发送请求开始,到接收到后端响应的时间,如果超过了这个时间,NGINX 会中止连接。

4、七层代理的实现

七层代理处理的是应用层协议,最常见的是 HTTP 或 HTTPS。它可以解析 HTTP 请求的详细内容(如 URL、请求头、Cookie、路径等),然后根据这些信息做出路由决策。

NGINX 七层代理配置方法;

  1. 首先需要在 NGINX 上通过 server 块配置虚拟主机,因为 NGINX 需要知道如何接收和解析客户端的请求。虚拟主机配置指定了监听的端口和域名。
  2. NGINX 默认集成了反向代理所需的模块,可以使用对应的指令将客户端的请求转发到指定的后端服务器。
  3. 由于反向代理服务器代表客户端发起请求,后端服务器通常需要了解客户端的一些信息,所以也需要对应的指令将客户端的相关请求头和变量传递给后端服务器
    例如:
bash 复制代码
http {
	server {
		# 指定后端服务器
		proxy_set_header http://127.0.0.1:8000
		# 客户端主机名
		proxy_set_header Host $host;
		# 传递客户端的真实 IP 地址
		proxy_set_header X-Real-IP $remote_addr;
		# 记录经过代理服务器链的每个客户端 IP 地址。(一般简单的代理可以省略这个配置)
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		# 将客户端请求使用的协议(http 或 https)传递给后端服务器。
		proxy_set_header X-Forwarded-Proto $scheme;
	}
}

5、四层代理的实现

四层指的是OSI参考模型中的运输层,NGINX原生支持四层代理,通过stream配置块可以实现四层代理的功能,从而实现在 传输层(第4层) 上处理 TCP 和 UDP 流量;


NGINX 四层代理的配置方法:

1、首先需要通过在 stream 这个顶层块中配置 server块,用于接收客户端的请求;

2、在server块中通过对应的指令来将请求转发给后端服务器;

例如:

bash 复制代码
stream {
    server {
        listen 3306;  # NGINX 监听端口(例如 MySQL 默认端口)
        proxy_pass 192.168.1.10:3306;  # 所有请求转发到指定的后端服务器
        proxy_timeout 10s;  # 配置代理超时
        proxy_connect_timeout 5s;   # 设置连接超时时间
    }
}

NGINX 负载均衡

NGINX的负载均衡其实就是反向代理的一个扩展,反向代理默认就是将客户端的请求代理到一个指定的服务器处理,负载均衡就是在配置反向代理的时候,先设置一组后端服务器,然后通过某种策略,将请求交给这一组后端服务器处理,这样就可以减轻单个服务器处理的压力。

1、负载均衡的策略

  • 轮询方式:NGINX配置负载均衡时,默认使用的负载均衡方式;

  • 最少连接:将请求分发到当前连接数最少的服务器,适用于长连接场景(如数据库连接)。

  • IP 哈希:据客户端的 IP 地址生成哈希值,确保同一个客户端始终连接到同一台后端服务器。

  • 指定权重:为后端服务器设置不同的权重,流量会按权重比例分配到后端。

2、upstream 指令块

NGINX负载均衡配置时,需要指定一个服务器池,即哪些后端服务器可以接收这个请求,通过 upstream 指令块可以配置负载均衡的后端服务器集群。

它允许指定多个后端服务器的 IP 地址或主机名,并定义负载均衡的策略,使得客户端请求可以根据不同的算法和规则分配给这些服务器。

如果是配置四层负载均衡,upstream块位于 stream 配置块中,如果是配置七层负载均衡,upstream块位于 http块中;

upstream 基本语法:

bash 复制代码
upstream <group_name> {
    server <server1>;
    server <server2>;
    ...
}
  • <group_name>:指定一个后端服务器组的名称。该名称将在 proxy_pass 或其他指令中引用,作为负载均衡的目标。
  • server <server>:定义每个后端服务器。可以是 IP 地址、域名或主机名。

3、server 指令

在 NGINX 中,server 指令在 upstream 配置块中用于定义一个后端服务器。upstream 块指定了后端服务器的集合,并且在反向代理时,NGINX 会根据负载均衡策略将请求转发给这些后端服务器。

server 语法格式server <server_address> [parameters];

  • <server_address>:后端服务器的地址,通常是一个 IP 地址或主机名,NGINX 将请求转发到该服务器。
  • [parameters]:可选的参数,用于指定服务器的配置选项,如权重、最大连接数、健康检查等。

指定负载均衡的方式:

  • 轮询方式:server指令的参数中,如果不指定负载均衡的方式,默认是轮询。
  • 最少连接:在upstream块中定于服务器池时,加上 least_conn;
  • IP 哈希:在upstream块中定于服务器池时,加上 ip_hash;
  • 指定权重:在upstream块中,通过server指定服务器时,在后面加上weight=xx权重

server指令的其他参数:

  • max_conns:限制一个服务器的最大并发连接数。超过这个限制的请求将被转发到其他服务器。

  • down:标记该服务器为关闭状态,NGINX 会将请求从该服务器转发到其他健康的服务器。

  • backup:标记该服务器为备用服务器,只有当所有其他服务器都无法处理请求时,备用服务器才会接收请求。

  • fail_timeout:指定后端服务器失败的超时。如果服务器在指定时间内无法响应,NGINX会认为该服务器不可用,并将请求转发给其他服务器。默认是10s

  • max_fails:指定一个服务器允许失败的最大次数。如果该服务器在指定次数内失败,NGINX会认为该服务器不可用,并将请求转发给其他服务器。默认是1

4、NGINX 四层负载均衡

  1. 在stream块中,通过 upstream 块来定义后端服务器池,即参与负载均衡的服务器;

  2. 在stram块中,通过 server 块来定义一个虚拟主机,指定监听端口等信息;

bash 复制代码
# 默认轮询:
upstream mysql_3306 {
    server 10.0.4.22:3306;
    server 10.0.4.23:3306;
}

# 最少连接
upstream mysql_3306 {
    least_conn;
    server 10.0.4.22:3306;
    server 10.0.4.23:3306;
}

# IP哈希:
upstream mysql_3306 {
    ip_hash;
    server 10.0.4.22:3306;
    server 10.0.4.23:3306;
}

# 指定权重:
upstream mysql_3306 {
    server 10.0.4.22:3306 weight=3;  # 权重为3
    server 10.0.4.23:3306 weight=1;  # 权重为1
}

5、NGINX 七层负载均衡

  1. 在http块中,通过upstream块来定义后端服务器池;

  2. 在http块中,通过server 块来定义一个虚拟主机,指定监听端口等信息;

bash 复制代码
http {
    upstream web_servers {
        server 10.0.0.1;
        server 10.0.0.2;
    }

    server {
        listen 80;
        proxy_pass http://web_servers;  # 使用 upstream 配置的后端服务器池
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

NGINX 优化策略

1、服务配置优化

bash 复制代码
# 设置为与系统 CPU 核心数相同,或者在负载较高时适当增大。
worker_processes  auto; 

# 启用NGINX的压缩功能,这样将数据以响应报文发送给客户端的时候,可以减少传输量
gzip  on;

# 优化静态文件的传输性能,可以降低CPU使用率
# 优化静态文件的传输性能
sendfile        on;
#  #  优化传输效率
tcp_nopush      on;
#  减少传输延迟
tcp_nodelay     on;

# 响应头中隐藏NGINX的版本信息
server_tokens off;

# 如果客户端请求某个目录,该目录下没有索引文件,禁止列出该目录下的内容
autoindex  off;

# 虚拟服务器中,配置禁止客户端访问隐藏文件
server {
    location ~ ^/\. {
        deny all;
    }
}

2、设置缓存策略

(1)Cache-Control 响应字段

通过配置静态资源的缓存策略,客户端可以将一些资源缓存在本地,下次访问时就不需要再次请求同样的静态资源,以减少带宽消耗和服务器负载,提高加载速度。

Web服务器中的缓存使用过响应报文中的 Cache-Control 响应字段控制的,通过这个字段可以控制客户端是否需要将某次请求的资源缓存到本地。

Cache-Control 常用的值有以下几个:

  • public:客户端发起一个请求,如果Cache-Control 设置为public,表示任何客户端都可以缓存这个响应的数据;

  • private:客户端发起一个请求,如果Cache-Control 设置为private,表示只有浏览器这种客户端才能缓存该响应数据;

  • no-cache:客户端发起一个请求,如果Cache-Control 设置为no-cache,表示即使缓存了数据,在使用之前必须向服务器进行验证,确保内容是最新的。

  • no-store:会完全禁用缓存,响应数据不被存储在客户端或任何中间缓存(包括代理服务器等)中。用于避免缓存敏感数据。

  • max-age:指定响应可以被缓存的最大时间(以秒为单位)。超过这个时间后,缓存将视为失效,失效就需要重新从服务端请求;

  • must-revalidate:当缓存过期时,客户端或缓存服务器必须向源服务器重新验证响应,确保数据的有效性。即使缓存未过期,验证失败时也需要重新获取数据。

  • s-maxage:与 max-age 类似,但是专门用于共享缓存(如代理服务器和 CDN)环境;

  • proxy-revalidate:类似于 must-revalidate,但仅适用于共享缓存(代理服务器)。

(2)Expires 响应字段

Expires 相应字段的值是也给日期,表示缓存内容在此时间之后将被认为过期,客户端应该重新向服务器请求资源。一般与 Cache-Control 一起使用,以控制缓存策略。
Expires 是 HTTP/1.0 的特性,只会告诉客户端资源的过期时间点,不考虑缓存是否仍然有效。如果客户端时间不对,可能会导致过期判断不准确。

Cache-Control是从 HTTP/1.1的特性,通过max-age字段可以控制缓存生存时间,所以一般现在都是使用Cache-Control来控制响应时间,但是为了兼容旧浏览器,所以有的时候可能也需要将Expires字段加上。

(3)Etag 响应字段

ETag 是HTTP响应报文中的一个字段,是 HTTP 协议的标准,是一种由服务器生成的唯一标识符,用于标识资源的特定版本。可以基于文件内容(如修改时间、文件大小或文件哈希等)来生成。

当客户端(例如浏览器)再次请求资源时,它会带上之前请求时收到的 ETag,服务器会用它来判断资源是否变化。如果资源发生变化,就重新请求资源,而不是使用缓存的资源。如果资源没有变化,返回的是304状态码。所以通过 Cache-Control 可以控制存多久后过期,通过Etag可以让客户端知道缓存是否已经过时;


NGINX 默认情况下会对静态资源生成 ETag,而且这个 ETag 通常是基于 文件的修改时间(Last-Modified响应字段) 来生成;所以不需要额外的Etag配置;

(4)expires 指令

expires 指令是NGINX提供的一个简化缓存控制的指令,用来控制缓存过期时间的,通过设置 expires 就可以影响到 响应头中的ExpiresCache-Control 字段。

例如:

bash 复制代码
expires  8600s;

# 使用该指令时,NGINX会设置 Cache-Control 头,Cache-Control: max-age=8600
# 同时,NGINX 会自动生成一个 Expires 头,指示一个固定的日期和时间,表示该资源的过期时间。这个时间是当前时间加上 8600s

例如:NGINX 配置静态资源缓存策略

bash 复制代码
    # 静态资源缓存与跨域配置
    location ~* \.(ico|pdf|flv|jpg|jpeg|png|gif|woff|js|css|swf|json|kml|b3dm|pptx|mp4|mpg|zip|fbx|xlsx|xls)$ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000";
    }

3、NGINX 服务器优化

(1)优化资源限制

在Linux操作系统中,有一个PAM(Linux 系统中负责管理用户身份验证的模块化框架)系统,这个PAM系统提供了一个名为PAM limits 模块 ,通过这个模块可以用来限制和管理系统资源的使用;

PAM limits 模块的配置文件是 /etc/security/limits.conf ,通过在配置文件中定义资源的使用策略,从而实现对系统资源的管理。


配置文件格式限制的用户或用户组 限制的类型 限制的资源类型 给定资源的值

限制的用户或用户组:

  • 用户名:表示特定的用户
  • @groupname:表示特定的用户组
  • *:表示root用户

限制的类型

  • soft:软限制(可以动态增加,但有最大限制)。
  • hard:硬限制(不能超过的最大限制,通常由管理员设置)。
  • -:无类型(适用于所有类型,软限制和硬限制都设置)。

限制的资源类型:

  • core:控制 core dump 文件的大小。
  • nproc:控制最大进程数。
  • nofile:控制最大打开文件数。
  • memlock:控制最大内存锁定大小。
  • msgqueue:控制最大消息队列大小。

给定的资源值:

  • unlimited:表示无限制
  • 数字:表示不能超过这个数字指定值

例如:

bash 复制代码
vim /etc/security/limits.conf  
*    -   core       unlimited # 允许生成无大小限制的 core dump (程序崩溃时生成的转储文件) 文件
*    -   nproc       1000000  # 定义  每个用户 可用的最大进程数
*    -   nofile      1000000  # 设置  每个用户 允许打开的最大文件数
*    -   memlock     32000    # 限制用户可以锁定到内存中的最大内存量(KB)
*    -   msgqueue    8192000  # 设置每个用户可以使用的最大消息队列的大小(字节)

NGINX 实现 LNMP

使用NGINX实现LNMP架构,只能通过FastCGI协议来和外部应用程序,从而实现动态请求的处理,Apache做为Web服务器实现的LAMP架构,就有模块接口模式和FastCGI模式;

  • 静态请求:客户端请求的内容固定不变,具有幂等性。这些资源一般就是存放在Web服务器上;例如html文件、css、图片等
  • 动态请求:客户端请求的内容会根据不同的请求生成或者更新的资源。每次请求时,内容可能会不同,通常是基于用户的输入、请求参数或数据库中的数据生成。例如,PHP文件、python文件等;

1、LNMP数据流向

  1. 客户端发起请求,NGINX做为Web服务端,通过对应的配置来获取这个请求,判断是返回静态资源还是返回动态资源;

  2. 如果是PHP动态请求,NGINX 会通过 FastCGI 协议将请求传递给 PHP-FPM。

  3. PHP-FPM接收到NGINX传递的请求后,会调用PHP解释器来处理客户端发起的动态请求,这个时候可能涉及到MySQL数据库的操作,PHP解释器会根据代码里面的相关设置来调用MySQL数据库进行数据存取操作;

  4. PHP解释器处理完对应的php文件后,会将输出的数据返回给PHP-FPM,PHP-FPM会将这些数据返回给NGINX;

  5. NGINX将数据封装为响应报文,然后再返回给客户端;

2、CGI/FastCGI 协议

CGI协议是应用层协议,是一种Web服务器和外部应用程序(如 PHP、Perl、Python 脚本等)之间的通信标准,一般常见的Web服务器,例如IIS、NGINX、Apache都是支持CGI协议的。CGI的开销大,效率低,并且不支持高并发,所以一般用的是改良版的FastCGI协议;

FastCGI 是CGI协议的改良版本,拥有更好的性能和更快的响应速度,现在一般都没有用CGI了,因为CGI存在很多缺点。用的都是FastCGI实现动态资源的请求和响应;

所以Web服务器要和后端的解释器进行通过,需要使用一个实现FastCGI 协议的服务做为中介。这样Web服务器和这个FastCGI 服务通信,FastCGI 和后端PHP解释器通信;

3、PHP-FPM 组件

PHP-FPM(FastCGI Process Manager)是 PHP 生态中的一个独立组件,用于再Web服务器和PHP解释器通信时,管理 FastCGI 请求。它充当了 NGINX 和 PHP 解释器之间的桥梁,NGINX 将请求通过 FastCGI 协议传递给 PHP-FPM,后者调用 PHP 解释器处理 PHP 脚本并返回结果给 NGINX,再由 NGINX 将响应发送给客户端。

所以在LNMP架构中,需要使用到PHP-FPM来做为Web服务器和PHP解释器的桥梁。在编译安装PHP解释器时,通过加上--enable-fpm 这个选项,可以在编译源码的时候将 PHP-FPM 这个组件也给安装上(如果是编译安装的PHP,然后使用仓库在线安装的PHP-FPM,可能会有问题);


NGINX 和 PHP-FPM通信:

NGINX提供了一个名为 ngx_http_fastcgi_module 的模块,通过这个模块提供的对应指令,就可以实现NGINX和PHP生态中实现FastCGI协议的组件PHP-FPM通信,这样NGINX就可以以传递参数的形式,让PHP-FPM调用PHP解释器来处理对应的PHP脚本文件,从而实现动态资源的处理;

NGINX 配置LNMP

1、PHP 安装配置

PHP安装:生产环境中,一般采用编译源码的形式来安装PHP解释器,PHP源码下载地址:https://www.php.net/releases/


PHP配置 :编译安装的PHP,默认没有配置文件,可以先执行 php --ini 查看存放配置文件的路径;因为编译安装完成后,会在源码包里生成两个配置文件模板,根据实际情况来对PHP解释器进行配置;

  • php.ini-development:这个配置文件是为开发环境优化的。可能会启用一些不适合生产环境的设置,例如显示错误到输出到屏幕
  • php.ini-production:这个配置文件是为生产环境优化的。此配置文件通常配置为将错误记录到服务器日志中,而不是显示在用户的浏览器上。

PHP常用指令

  • 查看PHP的详细信息:通过在php脚本中使用 phpinfo()函数实现
  • 查看PHP的配置文件路径:php --ini
  • 查看PHP的版本信息:php --version 或 php -v
  • 查看PHP的所有配置项:php -i

2、PHP-FPM 安装配置

PHP-FPM 安装 :编译安装PHP的时候,需要通过加上--enable-fpm 这个选项,可以在编译源码的时候将 PHP-FPM 这个组件也给安装上(如果是编译安装的PHP,然后使用仓库在线安装的PHP-FPM,可能会有问题);


PHP-FPM 配置:

以 service 形式运行:在编译完PHP源码后,会在源码目录中的 sapi/fpm 目录中,提供了管理 php-fpm 的service文件php-fpm.service。在这个service文件中,默认 ProtectSystem = true,需要将其改为false,否则对某些目录没有写权限,导致service服务启动不起来;


PHP-FPM相关参数配置:

PHP-FPM组件的配置文件和PHP解释器的配置文件模板是放在一起的,所以可以基于对应的配置文件模板创建配置文件,配置文件一般需要修改以下参数:

  • user:指定PHP-FPM进程的运行用户,一般需要和运行NGINX工作进程的用户保持一致,防止权限问题;
  • group :指定PHP-FPM进程的运行用户组;
  • listen :设置PHP-FPM进程监听的Unix套接字或端口,如果是同意主机上运行NGINX和PHP-FPM,用套接字性能更好;
  • pm :设置PHP-FPM的进程管理方式
  • pm.max_children:设置PHP-FPM启动时初始的子进程数量,决定了在启动时有多少个PHP-FPM进程可以并发处理请求。
  • pm.min_spare_servers:设置PHP-FPM保持的最小空闲进程数量。
  • pm.max_spare_servers:设置PHP-FPM保持的最大空闲进程数量
  • request_terminate_timeout:设置PHP脚本最大执行时间,一般和PHP解释器中的request_terminate_timeout一致;
  • clear_env :设置是否清除环境变量

例如:

php 复制代码
$ cat /usr/local/php7/etc/php-fpm.d/www.conf | grep -E -v  '^;.*|^$'
[www]
user = nginx
group = nginx
listen = /run/php7-fpm.sock
listen.owner = ehigh
listen.group = ehigh
;设置PHP-FPM监听的套接字文件的权限为0660,意味着只有user和group可以读取和写入。
listen.mode = 0660
;设置PHP-FPM的进程管理方式为dynamic,表示PHP-FPM将根据流量的变化动态调整进程的数量。
pm = dynamic
;设置PHP-FPM最多可以启动的子进程数量
pm.max_children = 250
pm.start_servers = 30
pm.min_spare_servers = 30
pm.max_spare_servers = 30
;设置PHP脚本最大执行时间为300秒
request_terminate_timeout = 300
;一般设置为no
clear_env = no

3、NGINX 安装和配置

(1)fastcgi_pass 指令

指令作用:指定与哪个 FastCGI 服务器进行通信。但是 ==fastcgi_pass 本身并不会直接将请求转发给 FastCGI 服务器,它只指定了请求要转发的目标地址或套接字。==mNGINX 需要进一步处理请求的相关信息,才能正确地将请求交给 FastCGI 服务。

fastcgi_pass 指令格式:

  • IP:Portfastcgi_pass <server>[:port];

  • socketfastcgi_pass unix:/path/to/socket;

(2)fastcgi_split_path_info

fastcgi_split_path_info 指令作用:通过定义一个正则表达式来分割客户端请求的 URI,将其拆分成两部分(一部分是 PHP 脚本的路径,另一部分是 URI 中 PHP 脚本路径后面的路径信息)

将URI拆分为两部分后,会分别复制给$fastcgi_script_name$fastcgi_path_info 两个变量

  • $fastcgi_script_name:PHP 脚本的路径

  • $fastcgi_path_info:PHP 脚本路径后面的路径信息

一般使用默认的正则表达式即可:

bash 复制代码
fastcgi_split_path_info ^(.+?\.php)(/.*)$;

例如:客户福端发起的请求为http://10.0.28.6/LocationDeviceManage/index.php/home/Index/getEH100602SysInf

  • fastcgi_script_name的值为:/LocationDeviceManage/index.php
  • fastcgi_path_info 的值为:home/Index/getEH100602SysInfo

在 PHP 应用中,通常 index.php 是入口文件,它会接收请求并解析请求的路径信息。通过路由规则,PHP 程序会将 fastcgi_path_info 提供的路径信息(如 /home/Index/getEH100602SysInfo)映射到对应的控制器和方法,然后执行相应的操作。

例如:

bash 复制代码
ehigh@ubuntu:~$ php  ~/work/html/LocationDeviceManage/index.php  /home/Index/getEH100602SysInfo
{"type":1,"data":{"pk_sys_id":1,"sys_name":"定位管理软件、\t","sys_display_mode":1,"sys_param_mode":1,"sys_id_code":2208164379}}

通过 PATH_INFO 变量传递PHP 脚本路径后面的路径部分

在 PHP 的 URL 路由中,PATH_INFO 是用来传递 URI 中 PHP 脚本路径后面的路径部分。PHP 程序(如使用 MVC 框架的应用)会解析 PATH_INFO 来进行路由处理(例如确定哪个控制器和方法需要被调用)。所以将 PATH_INFO 传递给 PHP 解释器是一种约定;所以需要将PATH_INFO变量传递给FastCGI:

例如:设置PATH_INFO变量的值:

bash 复制代码
# Check that the PHP script exists before passing it
# 如果$fastcgi_script_name变量为空,就范围404
try_files $fastcgi_script_name =404;

# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
# 设置PATH_INFO变量的值
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;

# 指定默认的 FastCGI 文件,如果请求目录而不是文件时,NGINX 会自动使用此文件进行处理。
fastcgi_index index.php;

(3)fastcgi_index 指令

在NGINX中,通过 fastcgi_index 指令可以指定 FastCGI 服务器默认的脚本文件,当请求的 URI 指向一个目录而不是具体的文件时,NGINX 会自动将请求转发到这个默认的脚本文件。

例如:fastcgi_index index.php; 当用户请求一个目录,http://10.0.28.6/LocationDeviceManage/home/,根据 fastcgi_index index.php 指令,自动补充成 /LocationDeviceManage/home/index.php,并将请求转发到 FastCGI 服务进行处理。

(4)fastcgi_param 指令

通过这个指令,可以实现NGINX将请求转发给 FastCGI 服务器时,附带的必要参数。有了这些参数,才能正确处理请求和执行相应的脚本。

例如通过fastcgi_split_path_info ^(.+?\.php)(/.*)$; 可以实现获取到PHP的入口文件index.php和PHP 脚本路径后面的路径部分。但是需要转换为物理服务器上的绝对路径形式,所以就还需要传递其他参数给PHP-FPM才行;


常见的参数有这些:

bash 复制代码
# 传递 HTTP 请求中的查询字符串部分(即 URL 中 ? 后面的部分)
fastcgi_param  QUERY_STRING       $query_string;
# 指定 HTTP 请求的方法(例如 GET、POST、PUT、DELETE 等)
fastcgi_param  REQUEST_METHOD     $request_method;
# 指定客户端请求的资源类型,
fastcgi_param  CONTENT_TYPE       $content_type;
# 指定请求体的内容长度,即请求体的字节大小。
fastcgi_param  CONTENT_LENGTH     $content_length;

# GINX 将请求转发给的 FastCGI 应用的脚本路径。通常是应用的相对路径,和 SCRIPT_FILENAME 配合使用。
fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
# 客户端请求的完整URI(包括查询字符串)
fastcgi_param  REQUEST_URI        $request_uri;
# 客户端请求某个资源的URI(URL去掉协议、主机、端口和查询字符串)
fastcgi_param  DOCUMENT_URI       $document_uri;
# Web 服务器根目录的路径(root 或 alias 指令指定的路径)
fastcgi_param  DOCUMENT_ROOT      $document_root;
# 指定客户端发起请求使用的 HTTP 协议版本。
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
# 客户端发起请求使用的协议类型
fastcgi_param  REQUEST_SCHEME     $scheme;
# 指示请求是否使用 HTTPS 协议。如果请求使用 HTTPS,HTTPS 会被设置为 on;如果使用 HTTP,通常是空字符串。
fastcgi_param  HTTPS              $https if_not_empty;

# 指定使用的 CGI 版本。对于 FastCGI,通常是 CGI/1.1
fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
# 指定运行 Web 服务器的软件信息。在 NGINX 中,它会包含 NGINX 的版本号。
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

# 客户端的 IP 地址(即发起请求的用户的 IP 地址)。
fastcgi_param  REMOTE_ADDR        $remote_addr;
# 客户端的端口号,即http请求的源端口是多少
fastcgi_param  REMOTE_PORT        $remote_port;
# 服务器的 IP 地址。
fastcgi_param  SERVER_ADDR        $server_addr;
# 服务器监听的端口号。
fastcgi_param  SERVER_PORT        $server_port;
# 服务器的主机名或域名,通常是 NGINX 配置中的 server_name 指令指定的值。
fastcgi_param  SERVER_NAME        $server_name;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;

(5)scgi_param 指令

这个指令是用来指定如果NGINX和后端指定的进程使用SCGI(Simple Common Gateway Interface)协议进行通信时的一些参数,SCGI是FastCGI 的一种简化版本,提供了更高效、更简单的实现方式。作用也是将 HTTP 请求传递给外部应用程,但是要使用 SCGI 协议,除了配置 NGINX 以外,还需要后端服务支持 SCGI 协议才能正常处理请求。如果PHP和NGINX的中介是php-fpm,那么使用的是FastCGI协议;


SCGI常用的配置:

bash 复制代码
scgi_param  REQUEST_METHOD     $request_method;
scgi_param  REQUEST_URI        $request_uri;
scgi_param  QUERY_STRING       $query_string;
scgi_param  CONTENT_TYPE       $content_type;

scgi_param  DOCUMENT_URI       $document_uri;
scgi_param  DOCUMENT_ROOT      $document_root;
scgi_param  SCGI               1;
scgi_param  SERVER_PROTOCOL    $server_protocol;
scgi_param  REQUEST_SCHEME     $scheme;
scgi_param  HTTPS              $https if_not_empty;

scgi_param  REMOTE_ADDR        $remote_addr;
scgi_param  REMOTE_PORT        $remote_port;
scgi_param  SERVER_PORT        $server_port;
scgi_param  SERVER_NAME        $server_name;

例如:NGINX配置LNMP

bash 复制代码
# 这里通过location指令的优先级来对用户请求的URI进行处理和重写
# 正则匹配的优先级高于普通匹配,所以请求首先会匹配到正则location,因为不满足条件从而进入普通location重写
# 重写后的URI仍然会优先匹配正则location,所以就放置了递归重写的发生

# 80-site.conf 
server {
    listen 80;
    root /home/ehigh/work/html;
    index index.php index.html;

    location ~ ^/\. {
        deny all;
    }
  
    add_header Access-Control-Allow-Credentials true;

    # 静态资源缓存与跨域配置
    location ~* \.(ico|pdf|flv|jpg|jpeg|png|gif|woff|js|css|swf|json|kml|b3dm|pptx|mp4|mpg|zip|fbx|xlsx|xls)$ {
        expires 1y;
        add_header Cache-Control "public, max-age=31536000";

        add_header Access-Control-Allow-Origin *;

        error_page 405 =200 $uri;
    }

    # location
    location /LocationDeviceManage {
        rewrite ^/LocationDeviceManage/(.*)$ /LocationDeviceManage/index.php/$1 last;
    }

    # ehcommon
    location /EHCommon {
        rewrite ^/EHCommon/(.*)$ /EHCommon/index.php/$1 last;
    }
    
    # onlydoor
    location /OnlyDoor {
        rewrite ^/OnlyDoor/(.*)$ /OnlyDoor/index.php/$1 last;
    }

    location /iot {
        rewrite ^/iot/(.*)$ /iot/index.php/$1 last;
    }

    # 通用入口文件 PHP 处理
    location ~ ^/(LocationDeviceManage|EHCommon|OnlyDoor|iot)/index\.php {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php7-fpm.sock;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php7-fpm.sock;
    }
}

fastcgi-php.conf

bash 复制代码
# regex to split $uri to $fastcgi_script_name and $fastcgi_path
fastcgi_split_path_info ^(.+?\.php)(/.*)$;

# Check that the PHP script exists before passing it
try_files $fastcgi_script_name =404;

# Bypass the fact that try_files resets $fastcgi_path_info
# see: http://trac.nginx.org/nginx/ticket/321
set $path_info $fastcgi_path_info;
fastcgi_param PATH_INFO $path_info;

fastcgi_index index.php;
include fastcgi.conf;

fastcgi.conf

bash 复制代码
ehigh@ubuntu:/etc/nginx$ cat fastcgi.conf 

fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  REQUEST_SCHEME     $scheme;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
# fastcgi_param  SERVER_NAME        $server_name;
# 这里需要改为host,否则有重定向的话,会出错误
fastcgi_param  SERVER_NAME        $host;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param  REDIRECT_STATUS    200;
相关推荐
恩爸编程33 分钟前
Nginx常用配置详解(1)
nginx·nginx配置·nginx常用配置·nginx配置详细解释·nginx常用配置详解·nginx配置说明·nginx常用配置说明
whoami-433 分钟前
Linux基础入门
linux·运维·服务器
zym大哥大1 小时前
Shell自定义(二)
linux·windows
码农秃头老李1 小时前
系列1:基于Centos-8.6部署Kubernetes (1.24-1.30)
linux·kubernetes·centos
魏 无羡1 小时前
linux CentOS系统上卸载Kubernetes(k8s)
linux·kubernetes·centos
菜鸟恒1 小时前
Linux下安装docker
linux·docker·eureka
NiNg_1_2341 小时前
Linux中用户和用户管理详解
linux·运维·服务器
赵庆明老师2 小时前
允许某段网络访问Linux服务器上的MariaDB
linux·服务器·网络
二进制诗人2 小时前
linux中 umask 命令
linux·运维·服务器