Appearance
Nginx
Nginx介绍
Nginx是一款轻量级、高性能的 HTTP 和反向代理服务器,
Nginx 采用事件驱动的异步非阻塞模型,能够高效地处理大量并发连接。与传统的 Web 服务器(如 Apache)相比,Nginx 在性能表现上具有显著优势,尤其在高并发场景下,Nginx 能够保持较低的资源消耗,提供更快的响应速度
Nginx安装
安装环境准备
本文以 CentOS 系统为例进行安装演示。在安装 Nginx 之前,需要确保系统已经安装了必要的依赖包,Nginx 基于 C 语言开发,因此需要安装 C 语言编译环境以及其他相关依赖。执行以下命令安装依赖包:
bash
yum -y install gcc pcre-devel zlib-devel openssl openssl-devel其中, gcc 是 C 语言编译器, pcre-devel 用于支持 PCRE 正则表达式库(Nginx 配置中常用到正则表达式), zlib-devel 用于支持数据压缩, openssl 和 openssl-devel 用于支持 SSL/TLS 加密功能。
下载 Nginx 安装包
Nginx 官方网站提供了稳定版本和开发版本的下载。通常建议在生产环境中使用稳定版本,以确保系统的稳定性和安全性。访问 Nginx 官网的下载页面( nginx: download ),选择合适的稳定版本,本文以 nginx-1.24.0 为例,使用 wget 命令下载安装包:
bash
yum install wget
wget https://nginx.org/download/nginx-1.24.0.tar.gz解压与配置编译环境
下载完成后,解压 Nginx 压缩包,并进入解压后的目录进行编译环境配置:
bash
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0
./configure --prefix=/usr/local/nginx--prefix=/usr/local/nginx 参数指定了 Nginx 的安装目录为 /usr/local/nginx ,你可以根据实际需求进行调整。 configure 脚本会检查系统环境,确保满足 Nginx 编译所需的依赖条件,并生成相应的 Makefile 文件。
编译与安装
执行以下命令进行编译和安装:
bash
make & make installmake 命令根据之前生成的 Makefile 文件编译 Nginx 源代码, make install 则将编译好的 Nginx 二进制文件及相关配置文件安装到指定的目录(即 /usr/local/nginx )。
启动与基本管理
安装完成后,进入 Nginx 的安装目录 /usr/local/nginx/sbin ,可以使用以下命令对 Nginx 进行管理:
bash
# 查看版本
./nginx -v
# 检查配置文件语法
./nginx -t
# 启动Nginx
./nginx
# 停止Nginx
./nginx -s stop
# 重新加载配置文件(修改配置后使用)
./nginx -s reload为了方便使用,建议将 Nginx 的 sbin 目录添加到系统的环境变量中。编辑 /etc/profile 文件,在 PATH 环境变量中增加 /usr/local/nginx/sbin ,修改完成后执行 source /etc/profile 使配置生效。这样,在系统的任何目录下都可以直接执行 nginx 命令。
基础配置逻辑
Nginx 存放静态资源的核心是:通过 server 块区分不同访问入口(域名或端口),再用 location 块指定资源存放路径,让不同请求对应到正确的本地文件。
按域名 / 端口区分不同业务
text
# 用域名区分(需解析域名)
server {
listen 80;
server_name member.hltop.cn; # 会员业务域名
location / {
root html/member; # 资源存放在 Nginx安装目录/html/member
index index.html; # 访问根路径时默认找index.html
}
}
server {
listen 80; # 同一80端口,不同域名
server_name order.hltop.cn; # 订单域名
location / {
root /var/www/order;
index index.html;
}
}
-------------------------------------------------------
# 用端口区分(适合本地测试)
server {
listen 8081; # 用8081端口访问会员业务
location / {
root html/member;
index index.html;
}
server {
listen 8082; # 测试端口2
location / {
root /var/www/test2;
index index.html;
}
}root 指令:路径拼接方式
root 是最常用的指定资源目录的指令,它的路径拼接规则很简单:
最终文件路径 = root 指定的目录 + location 匹配的路径 + 请求的文件名
text
location /img/ {
root /var/www/static; # 根目录设为/var/www/static
}当客户端请求 http://domain.com/img/logo.png 时:
location匹配到/img/- 拼接路径:
/var/www/static(root) +/img/(location 匹配的路径) +logo.png(请求的文件名) - 实际查找的文件:
/var/www/static/img/logo.png
alias 指令:路径替换方式
alias 用于 替换 location 匹配的路径,适合需要重命名目录的场景。它的拼接规则是:
最终文件路径 = alias 指定的目录 + 请求中 location 之后的部分
(注意: alias 后面的目录路径必须以 / 结尾)
text
location /img/ {
alias /var/www/static/image/; # 用/image/替换/img/
}当客户端请求 http://domain.com/img/logo.png 时:
location匹配到/img/,但这个路径会被alias替换- 拼接路径:
/var/www/static/image/(alias) +logo.png(请求中/img/之后的部分) - 实际查找的文件:
/var/www/static/image/logo.png
root 和 alias 的核心区别
| 场景 | root 指令 | alias 指令 |
|---|---|---|
| 作用 | 设定根目录,路径叠加 | 替换 location 匹配的路径 |
| 路径要求 | 无特殊要求 | 目录必须以 / 结尾 |
| 适用场景 | 大多数静态资源映射 | 需重命名目录的场景(如 URL 显示 /img/,实际用 /image/ 目录) |
简单说: root 是「在指定目录下追加路径」, alias 是「直接替换路径」。根据实际目录结构选择即可。
HTTPS 配置
发布静态资源后,如果需要开启 HTTPS 协议,需要配置 Nginx 的 SSL 证书。
配置参考:
text
server {
listen 443 ssl;
server_name localhost;
ssl_certificate ssl/server.crt;
ssl_certificate_key ssl/server.key;
location / {
root html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}上述示例中证书server.crt和私钥server.keys使用的是相对位置,所在的ssl目录实际应该位于Nginx安装目录的conf目录下(在windows平台版本1.30.4的环境下,实测ssl目录要放在conf目录下才能被正确找到,放在安装目录启动会有失败日志
cannot load certificate "D:\PRODUCTION\nginx_8888_imis/conf/ssl/server.crt": BIO_new_file() failed (SSL: error:80000003:system library::No such process:calling fopen(D:\PRODUCTION\nginx_8888_imis/conf/ssl/server.crt, r) error:10000080:BIO routines::no such file),网上教程大部分是放在安装目录,不知是否是该版本的缺陷还是新旧版本差异)。当然,我们可以直接使用绝对路径。
正向代理与反向代理
正向代理
概念 正向代理是位于客户端和目标服务器之间的代理服务器。当客户端需要访问外部资源时,客户端将请求发送到正向代理服务器,代理服务器代替客户端向目标服务器发送请求,并将目标服务器的响应返回给客户端。
正向代理是指代理服务器代理 客户端 ,使得客户端可以访问被代理的服务器上的资源。举个例子,我们可以使用正向代理访问一些境外网站,这些网站被代理服务器所代理,客户端看到的是代理服务器响应的内容。这时,被代理的服务器并不知道客户端的存在,只知道代理服务器的存在。正向代理主要应用于隐藏客户端的 IP 地址、访问互联网被封锁的资源等场景
Nginx 实现正向代理配置 在 Nginx 中配置正向代理,需要编辑 Nginx 的配置文件,通常位于 /usr/local/nginx/conf/nginx.conf 。在 http 块内添加如下配置:
text
server {
listen 8080; # 代理服务器监听端口
resolver 8.8.8.8; # 指定DNS服务器,用于域名解析
location / {
proxy_pass http://$http_host$request_uri;
}
}上述配置中, listen 指令指定了代理服务器监听的端口为 8080 ,客户端将请求发送到该端口。 resolver 指令指定了 DNS 服务器地址(这里使用 Google 的公共 DNS 服务器 8.8.8.8 ),用于将域名解析为 IP 地址。 location / 块表示对所有请求进行处理, proxy_pass 指令将客户端的请求转发到目标服务器, $http_host 和 $request_uri 是 Nginx 的内置变量,分别表示客户端请求的主机名和请求的 URI。
配置完成后,检查配置文件语法并重新加载 Nginx 配置:
bash
nginx -t
nginx -s reload此时, 客户端需要将代理服务器的地址和端口配置到网络设置 中,才能通过 Nginx 正向代理访问外部资源。需要注意的是,Nginx 的正向代理默认不支持 HTTPS 站点,如果需要代理 HTTPS 请求,还需要进行额外的配置。
反向代理
概念 反向代理位于客户端与目标服务器之间。客户端向反向代理服务器发送请求,反向代理会依据配置规则,把请求转发到后端的目标服务器,再将目标服务器的响应回传给客户端。对客户端而言,它不清楚具体是后端哪台服务器处理了请求,仅与反向代理交互,反向代理隐藏了后端服务器的真实 IP 和架构细节。
反向代理常用于为服务器端提供服务,可实现负载均衡(比如按算法选合适服务器转发请求)、缓存加速、安全防护(隐藏后端信息、抵御直接攻击),还能进行 SSL 加密等,主要在数据安全性、访问速度、系统弹性等方面发挥作用。
Nginx 实现反向代理配置 在 Nginx 中配置反向代理同样需要编辑配置文件。假设后端有一台 Web 服务器,IP 地址为 192.168.1.100 ,端口为 8080 ,现在要通过 Nginx 反向代理将客户端对 http://example.com 的请求转发到该后端服务器。在 nginx.conf 文件的 http 块内添加如下 server 块配置:
text
server {
listen 80; # 监听端口
server_name example.com; # 域名或IP地址
location / {
proxy_pass http://192.168.1.100:8080; # 反向代理到后端服务器
proxy_set_header Host $host; # 设置请求头,将客户端请求的主机名传递给后端服务器
proxy_set_header X-Real-IP $remote_addr; # 设置请求头,将客户端的真实IP传递给后端服务器
}
}listen 指令指定 Nginx 监听的端口为 80 , server_name 指定了反向代理的域名或 IP 地址(这里假设为 example.com ,实际使用时需替换为真实的域名或 IP)。 location / 块表示对所有请求进行匹配处理, proxy_pass 指令将请求转发到后端服务器 http://192.168.1.100:8080 。 proxy_set_header 指令用于设置请求头信息,将客户端的一些信息(如主机名、真实 IP)传递给后端服务器,这在后端服务器需要根据这些信息进行处理时非常重要。
配置完成后,同样需要检查配置文件语法并重新加载 Nginx 配置,使配置生效。
这段配置的作用就是:当用户访问 example.com (通过 80 端口)时,Nginx 会自动将请求 悄悄转发 到后端的 http://192.168.1.100:8080 服务器,而用户完全感知不到这个转发过程 —— 在用户看来,自己就是直接访问 example.com 并得到了响应。
正向代理和反向代理区别
区别:
- 正向代理 :客户端明确知道自己在通过代理服务器访问目标服务器(比如设置浏览器代理),整个过程是 “客户端→代理→目标服务器”,客户端主动依赖代理才能完成请求。
- 反向代理 :客户端以为自己直接访问的是 “目标服务器”(实际是反向代理服务器的地址),完全不知道后端有多少台真实服务器,也不关心代理如何转发请求。对客户端来说,“反向代理服务器” 就是它眼中的 “目标服务器”,整个过程是 “客户端→反向代理(以为是目标服务器)→后端真实服务器”,代理行为对客户端完全透明。
在简单说:
- 正向代理是 “ 客户端主动找代理帮忙上网 ”;
- 反向代理是 “ 后端服务器偷偷用代理对外提供服务 ”,客户端被蒙在鼓里。
负载均衡算法
Nginx 支持多种负载均衡算法,每种算法都有其特点和适用场景:
1.轮询(Round Robin) :默认算法,每个请求按时间顺序逐一分配到不同的后端服务器。如果后端服务器出现故障,Nginx 会自动将其剔除,请求将分配到其他正常的服务器上。例如:
text
upstream backend_servers {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}2.权重(Weighted Round Robin) :为后端服务器设置不同的权重,权重越高的服务器被分配到的请求越多。适用于后端服务器性能不均的情况,例如:
text
upstream backend_servers {
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080 weight=1;
}这里 192.168.1.101 服务器的权重为 3, 192.168.1.102 服务器的权重为 1,那么在负载均衡时, 192.168.1.101 服务器被分配到请求的概率将是 192.168.1.102 服务器的 3 倍。
3. IP 哈希(IP Hash) :根据客户端的 IP 地址计算哈希值,将请求分配到固定的后端服务器上。这样可以确保同一客户端的请求始终被转发到同一台后端服务器,适用于需要保持会话一致性的场景,例如:
text
upstream backend_servers {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}四层代理
说到nginx代理,一般都指七层代理。nginx也支持四层代理。
配置示例:
text
stream {
upstream mysql_backend {
server 10.0.0.1:3306;
server 10.0.0.2:3306;
}
server {
listen 3306;
proxy_pass mysql_backend;
}
}什么情况下使用四层代理? 非 HTTP 协议的代理 — 这是最核心的场景。MySQL、Redis、PostgreSQL、MongoDB、RabbitMQ、DNS 等都是 TCP/UDP 协议,七层代理根本无法处理,只能用四层。
追求极致性能 — 四层不解析应用层报文,转发延迟更低,吞吐更高。对于高并发短连接场景(如游戏服务器、物联网设备接入),四层代理的性能优势明显。
TLS 透传(SNI 路由) — 不想在负载均衡层解密 TLS(避免证书管理复杂度或保持端到端加密),四层可以根据 TLS 握手的 SNI 字段做路由,而不需要解密流量:
七层代理提供了路径路由、Header 操作、缓存、限流、灰度发布等丰富能力,这些是四层做不到的。只有当协议不是 HTTP、或者对性能/TLS 透传有硬性要求时,才选择四层。实际生产中,两者经常组合使用:四层在最前端做流量入口和 TLS 卸载/透传,七层在后面做精细化路由。
跨域问题(CORS)
跨域问题详解
1. 什么是跨域?
跨域是指浏览器出于安全考虑( 同源策略 ),限制一个域的网页去请求另一个域的资源。
- 同源 :指两个 URL 的 协议、域名、端口 完全一致。例如:
http://example.com与https://example.com(协议不同,跨域)http://example.com与http://api.example.com(域名不同,跨域)http://example.com:80与http://example.com:8080(端口不同,跨域)
2. 跨域的常见场景
- 前端页面(
http://frontend.com)请求后端 API(http://backend.com) - 静态资源(如图片、JS)从
http://a.com加载到http://b.com的页面中 - 前后端分离项目中,前端本地开发环境(
http://localhost:3000)请求后端服务器(http://localhost:8080)
3. 跨域的本质:浏览器的同源策略限制
同源策略是浏览器的安全机制,防止恶意网站窃取其他网站的资源或数据。当跨域请求发生时,浏览器会拦截响应(即使服务器正常返回数据),并在控制台报类似错误:
text
Access to fetch at 'http://backend.com/api' from origin 'http://frontend.com' has been blocked by CORS policy...Nginx 解决跨域的原理与配置
Nginx 解决跨域的核心思路是: 通过反向代理将跨域请求转为同域请求 。
即前端页面请求 Nginx 服务器(同域),Nginx 再转发请求到真实后端服务器,从而绕过浏览器的同源策略限制。
1. 场景假设
- 前端页面地址:
http://frontend.com(端口 80) - 后端 API 地址:
http://backend.com:8080(跨域,协议 / 域名 / 端口任一不同) - 目标:让前端通过
http://frontend.com/api访问后端 API,实现 “同域” 请求。
2. Nginx 配置示例
text
server {
listen 80;
server_name frontend.com; # 前端页面的域名(同域)
# 处理前端页面的静态资源(如 HTML、CSS、JS)
location / {
root /path/to/frontend; # 前端代码存放目录
index index.html;
}
# 反向代理后端 API,解决跨域
location /api/ { # 前端请求以 /api 开头的路径时,触发代理
proxy_pass http://backend.com:8080/; # 转发到真实后端(注意末尾的 / 含义)
# 关键:设置跨域相关响应头,允许浏览器接收
add_header Access-Control-Allow-Origin $http_origin; # 允许请求的源($http_origin 为动态值,或者为*允许所有的跨域调用)
add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS; # 允许的请求方法
add_header Access-Control-Allow-Headers Content-Type,Authorization; # 允许的请求头
add_header Access-Control-Allow-Credentials true; # 允许携带 Cookie(需前后端配合)
}
}3. 配置说明
**proxy_pass**转发规则 :
当前端请求http://frontend.com/api/user时,Nginx 会转发到http://backend.com:8080/user(/api/被替换为后端的根路径)。- 跨域响应头作用 :
Access-Control-Allow-Origin:告诉浏览器 “允许frontend.com这个源的请求”,$http_origin表示动态匹配请求的源(更灵活)Access-Control-Allow-Credentials:如果前端请求需要携带 Cookie 或认证信息,必须设置为true,且Allow-Origin不能为*(需指定具体域名)。
4. 效果
前端只需请求同域的 http://frontend.com/api/xxx ,Nginx 自动转发到后端,浏览器认为是同域请求,不再拦截,跨域问题解决。
动静态资源分离
什么是动静态资源分离?
动静态分离是指将网站的 动态资源 和 静态资源 分开部署、管理和访问的架构设计。
- 静态资源 :即所说的前端资源,指内容不随请求变化的文件,如 HTML、CSS、JS、图片(jpg/png)、视频、字体等(可被浏览器缓存)。
- 动态资源 :即后端请求,指内容随请求参数或业务逻辑动态生成的资源,如 PHP/JSP/Java 代码生成的页面、API 接口返回的 JSON 数据等(需服务器计算后返回)。
通过分离,可让静态资源由专门的服务器(如 Nginx)处理,动态资源由应用服务器(如 Tomcat、Node.js)处理,从而提升整体性能。
为什么需要动静态分离?
- 减轻应用服务器压力 :
静态资源访问频率高(如首页图片、样式表),若全部由处理动态逻辑的应用服务器承担,会占用其 CPU / 内存资源,影响动态请求的响应速度。 - 提升静态资源加载速度 :
Nginx 处理静态资源的效率远高于应用服务器(底层基于异步非阻塞 IO,适合高并发静态文件读取),且可配合浏览器缓存、CDN 进一步加速。 - 便于缓存和扩展 :
静态资源可设置长期缓存策略,或通过 CDN 分发到边缘节点;动态资源则可专注于业务逻辑,按需扩容应用服务器。
Nginx 实现动静态分离的核心思路
Nginx 通过 **location** 指令匹配不同资源路径 ,将静态资源请求直接由 Nginx 本地处理(读取服务器文件),动态资源请求转发到后端应用服务器(如 Tomcat、Spring Boot 等)。
假设场景:
- 静态资源(CSS/JS/ 图片)存放路径:
/usr/share/nginx/static - 动态资源由后端应用服务器
http://192.168.1.101:8080处理
配置如下:
text
server {
listen 80;
server_name example.com; # 网站域名
# 1. 处理静态资源:匹配以 /static/ 开头的路径(如 CSS、JS、图片)
location /static/ {
root /usr/share/nginx; # 静态资源根目录(实际路径为 /usr/share/nginx/static/)
try_files $uri =404; # 若文件不存在,返回404
}
# 2. 处理动态资源:所有非静态资源的请求转发到后端应用服务器
location / {
proxy_pass http://192.168.1.101:8080; # 转发到动态服务器
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}常见问题及解决方法
访问单页面应用404问题
单页面应用部署时,常遇到刷新页面后,路由跳转失败的问题。例如:vue工程打包输出dist目录,我们使用nginx部署,常配置如下:
text
location / {
root html/dist;
index index.html index.htm;
}首次访问如:http://localhost:8080,页面正常跳转http://127.0.0.1:8080/mine/flight-routes, 再刷新页面,出现404错误。 这是 Vue SPA 部署到 nginx 的经典问题。因为 Vue Router 是在客户端处理路由,而 nginx 是在服务器端处理路由。原因:刷新浏览器时,nginx 收到 /mine/flight-routes 的 GET 请求,去 html/dist/ 目录下找 mine/flight-routes 文件,找不到就返回 404。Vue Router 的前端路由对 nginx 来说是不可见的。
在 nginx 配置的 location / 块里加一行 try_files 即可:
text
location / {
root html/dist;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}这样 nginx 找不到对应文件时,会把请求交给 index.html,由 Vue Router 在客户端解析路由,页面就能正常渲染了。改完后 nginx -s reload 重新加载配置即可。
try_files 是 nginx 的一个指令,它按顺序依次检查多个文件路径,第一个存在的就直接返回,全部不存在则把请求交给最后一个参数处理。
try_files $uri $uri/ /index.html; 展开来就是三步查找:
$uri — 把请求的路径当作文件去找。比如访问 /assets/index.2568ccb9.js,nginx 就去 root 目录下找 assets/index.2568ccb9.js 这个文件。找到了就直接返回,这是正常的静态资源命中路径。
$uri/ — 把请求路径当作目录去找。比如访问 /foo,nginx 去找 foo/ 目录,如果存在就尝试返回目录下的 index.html。这个在实际 SPA 项目中用得少,主要是为了兼容某些路径末尾不带斜杠的目录访问场景。
/index.html — 前面两步都没命中,就把 /index.html 作为内部重写目标返回给浏览器。注意这不是 302 重定向,是内部 rewrite,浏览器地址栏不会变。浏览器拿到 index.html 后,Vue Router 接管,根据 URL 中的 /mine/flight-routes 渲染对应组件。
整个流程用你的场景举例:
用户首次访问 http://127.0.0.1:8080 → nginx 返回 index.html → Vue 启动 → Router 跳转到 /mine/flight-routes(纯客户端行为,不发 HTTP 请求)。
用户刷新页面 → 浏览器发 GET /mine/flight-routes → nginx 查找 html/dist/mine/flight-routes 文件(不存在)→ 查找 html/dist/mine/flight-routes/ 目录(不存在)→ 最终返回 html/dist/index.html → Vue 启动 → Router 解析 URL 并渲染页面。
没有 try_files 的情况下,nginx 找不到文件就直接 404 了,根本不会尝试返回 index.html。