Nginx使用指南
Nginx 是一款广泛使用的高性能 HTTP 和反向代理服务器,它以事件驱动的方式处理请求,能够高效地管理大量并发连接。Nginx 的配置灵活,支持丰富的功能模块,如负载均衡、缓存支持、HTTP认证等,这使得它成为搭建现代Web应用和服务的理想选择。其稳定性高、资源消耗少,易于维护和扩展,特别是在处理静态文件及用作反向代理时表现出色。
一、nginx 安装与配置
1. 安装与启动
服务器安装 Nginx 一般只需两行命令:
# 安装nginx
yum install -y nginx
# 启动nginx
systemctl start nginx
# 查看nginx运行状态
systemctl status nginx
2. 配置文件
Nginx 的配置文件一般位于/etc/nginx
目录下。主要关注nginx.conf
和conf.d
目录。
我们基本只需要关注文件nginx.conf
和conf.d
目录,下面是一份nginx.conf
配置文件,不懂也不要怕,基本都不需要改动,默认80服务已经开启了。
user nginx; # nginx进行运行的用户。指定 Nginx 进程的运行用户。在此,Nginx 将以 nginx 用户的身份运行。这是出于安全考虑,避免使用 root 用户运行服务。
worker_processes auto; # 指定 Nginx 的工作进程数量
error_log /var/log/nginx/error.log; # 错误日志
pid /run/nginx.pid; # 指定 Nginx 主进程的 PID 文件路径
include /usr/share/nginx/modules/*.conf; # 引入 Nginx 模块配置文件
# 用于设置与工作进程有关的事件处理参数
events {
worker_connections 1024; # 指定每个 Nginx 工作进程可以打开的最大连接数
}
http {
# 定义日志格式。变量含义:$remote_addr: 客户端 IP 地址、$remote_user: 客户端用户(如果有)、$time_local: 本地时间、$request: 请求行(请求方法、URI 和协议)、$status: 响应状态码、$body_bytes_sent: 发送给客户端的字节数、$http_referer: 来源页面、$http_user_agent: 客户端的用户代理信息、$http_x_forwarded_for: 经过的代理链的 IP 地址
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 日志的存储位置和格式。将日志记录到 /var/log/nginx/access.log 文件中,使用上面定义的 main 格式
access_log /var/log/nginx/access.log main;
sendfile on; # 启用高效的文件传输
tcp_nopush on; # 在发送大文件时优化 TCP 包的传输
tcp_nodelay on; # 确保小数据包立即发送,减少延迟
keepalive_timeout 65; # 设置 HTTP keep-alive 连接的超时时间
types_hash_max_size 4096; # 设置 MIME 类型哈希表的最大大小
include /etc/nginx/mime.types; # 引入 MIME 类型配置文件,使 Nginx 能够根据文件扩展名确定文件类型
default_type application/octet-stream; # 设置默认的 MIME 类型
# *** 引入的nginx配置文件,可以放在 Nginx 配置文件的多个层级中,方便管理 ***
include /etc/nginx/conf.d/*.conf;
# 定义一个虚拟主机配置
server {
listen 80; # 服务启动的端口
listen [::]:80; # 支持ipv6协议。[::]: 这是 IPv6 的表示方式,表示所有可用的 IPv6 地址
server_name _; # 指定服务器的域名或IP地址。在这里使用 _ 表示匹配所有的请求,适用于没有特别指定的域名的情况
root /usr/share/nginx/html; # 设置服务器的根目录为 /usr/share/nginx/html。Nginx 将从这个目录提供静态文件
error_page 404 /404.html; # 找不到资源重定向到404页面
location = /40x.html {}; # 定义处理 /40x.html 的空位置块,通常是用于预防直接访问该页面
error_page 500 502 503 504 /50x.html; # 系统错误重定向50x页面
location = /50x.html {}; # 定义处理 /50x.html 的空位置块,同样用于防止直接访问
}
# server {
# listen 443; # 支持https协议
# server_name _;
# root /usr/share/nginx/html;
# ...
# }
}
我们可以看到该文件分成了多层,我们逐层分析一下
第一层:
user
指定 Nginx 进程的运行用户。通常在主配置文件的最上方进行设置,以便控制整个 Nginx 实例的权限error_log
指定访问日志的存储路径和格式。一般在 http 块中设置,也可以在 server 或 location 块中覆盖http
定义与 HTTP 相关的配置。http 块是 Nginx 配置的核心部分,通常包含多个 server 块
...
第二层(http):
log_format
定义日志格式。通常在 http 块中设置,也可以在 server 或 location 块中覆盖access_log
指定访问日志的存储路径和格式。通常在 http 块中设置,也可以在 server 或 location 块中覆盖include
引入其他配置文件。通常用于将多个配置文件合并为一个,便于管理。可以灵活地放置在 http、server 和 location 块中,具体取决于配置文件的组织结构和需求server
定义虚拟主机配置。通常包含 listen、server_name 和 location 等指令,用于配置服务器的监听端口、域名和路径
...
第三层(server):
listen
指定监听的端口号。通常用于配置服务器的监听端口,以便接收客户端的请求server_name
指定服务器的域名或 IP 地址。通常用于配置虚拟主机的域名或 IP 地址,以便区分不同的服务器,_ 通常用于匹配所有未特别指定的请求root
指定服务器的根目录。通常用于设置服务器提供静态文件的位置,如 HTML、CSS 和 JavaScript 等。可在 server 或 location 块中设置,影响请求的文件查找路径error_page
定义错误页面。通常用于配置自定义的错误页面,如 404、50x 等状态码对应的页面location
定义 URL 路径匹配规则。通常用于根据请求的 URI 或其他特征,将请求映射到不同的处理逻辑
...
第三层(location):
alias
定义路径别名。通常用于将请求的 URI 重定向到另一个路径,如将 /images/logo.png 映射到 /usr/share/nginx/htmlindex
指定默认文件。通常用于配置默认的页面,如 index.html、index.php 等try_files
尝试访问指定文件。通常用于配置文件查找路径,如当请求的 URI 不存在时,尝试访问其他文件
...
3. 配置文件拆分
在http下可以有多个Server
,启动多个服务,但如果都写在一个文件里面,文件就越来越大了,那么为了便于管理多个服务,我们要对nginx.conf
进行拆分。
conf.d
目录下一般是空的,我们新建文件web.conf
或者任意命名的以.conf结尾的文件,即可被Nginx使用。
因为在
nginx.conf
中有include /etc/nginx/conf.d/*.conf;
我们通过这一行语句发现,include帮助我们引用conf.d下以.conf结尾的配置文件。
完成后执行nginx指令
# 检查nginx配置文件是否正确,如果错误会提示具体的错误信息
nginx -t
# 重新启动nginx服务
nginx -s reload
观察日志,此时发现Nginx就重新启动了,读取的是新的配置文件。
其他操作nginx的指令
nginx -s stop
nginx -s start
二、部署单页面应用
我们快速创建一个Vue单页面应用,这里使用npm create vue@latest
快速创建,然后修改App.vue文件
<script setup lang="ts">
import { RouterLink, RouterView } from 'vue-router'
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<header>
<div class="wrapper">
<h1>Nginx 测试应用</h1>
<nav>
<RouterLink to="/">Home</RouterLink>
<RouterLink to="/about">About</RouterLink>
</nav>
</div>
</header>
<RouterView />
</template>
<style scoped>
</style>
然后运行npm i
, npm run build
生成dist目录,将该目录文件迁移到服务器的目录/usr/share/nginx/html
下。
修改上述新建的web.conf
文件,修改为如下内容:
server {
# 监听的端口为 9000
listen 9000;
# 指定服务器的名称为 localhost。这通常用于本地开发和测试
server_name localhost;
# 虚拟主机(服务器)配置的根路径
root /usr/share/nginx/html;
location / {
# 当请求 URI 匹配到这个 location 时,Nginx 会使用 alias 指定的路径,而不是 root 指定的路径
alias /usr/share/nginx/html/dist/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
}
初始情况下服务器需要配置安全组规则,允许相关端口被访问。
最后访问外网IP:9000,发现页面正常渲染了。
上述demo的路由模式是history
模式,即便在/about下,刷新页面也是正常的,因为上面的location中配置了try_files
三、配置反向代理、负载均衡
1. 反向代理
反向代理的用途很多,这里我们看一个常用的,代理请求的接口。我们在发布时前端的域名和后端api服务的域名经常不一致,此时就可以使用Nginx配置反向代理来解决这个问题。
代理的时候要注意添加必要的参数,帮助后端获取一些客户端的请求数据,例如:
server {
location /api {
# 指定将匹配到的请求转发到指定的后端服务器。所有以 /api 开头的请求将被转发到 http://backend1.example.com。例如,请求 /api/data 将被转发到 http://backend1.example.com/api/data
proxy_pass http://backend1.example.com;
# 将原始请求的 Host 头传递给后端服务器
proxy_set_header Host $host;
# 将客户端的真实 IP 地址传递给后端服务器
proxy_set_header X-Real-IP $remote_addr;
# 将经过的代理链中的 IP 地址传递给后端服务器。$proxy_add_x_forwarded_for 变量会自动附加当前客户端的 IP 地址到原有的 X-Forwarded-For 头中
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
2. 负载均衡
Nginx可以作为负载均衡服务器使用,通过配置upstream
来分发流量,同时可以配置一些参数:
weight
设置每个后端服务器的权重,权重越高,获得的请求比例越多ip_hash
:将来自同一 IP 地址的请求始终转发到同一台后端服务器,适合需要保持会话的场景max_fails
: 设置在将后端服务器标记为不可用之前允许的最大请求失败次数backup
标记某个后端服务器为备用服务器,只有在其他服务器不可用时才会被使用down
将某个后端服务器标记为暂时不可用
# 定义一个名为 backend 的上游服务器组
upstream backend {
ip_hash; # 启用 IP 哈希
server backend1.example.com;
server backend2.example.com;
server backend3.example.com weight=5;
server backend4.example.com max_fails=5;
server backend4.example.com backup;
server backend4.example.com down;
}
server {
location /api {
# 使用 upstream 定义的服务器组
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
四、配置 nginx 日志
Nginx日志也是很重要的一个内容,在我们请求资源出现问题时,要排查请求的资源是否到达Nginx,而且请求日志可以记录很多有用的信息。
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main gzip buffer=32k;
nginx日志主要涉及 access_log,log_format:
log_format
: 日志格式,通过nginx内置的变量来读取和排列,通常默认即可access_log
: 日志输出的地址、使用格式、是否压缩、buffer是否当日志大于32k后吸入磁盘
五、其他常用配置
1. 配置Gzip压缩
作为前端性能优化的一种方式,Gzip是简单且有效的,尽管目前前端对于静态资源会进行压缩,但Gzip依然可以在网络传输过程中对文件进行压缩
下面这些字段可以放在http
、server
、location
指令模块
http {
# 开启关闭
gzip on;
# 压缩的文件类型
gzip_types text/plain text/css application/javascript;
# 过小的文件没必要压缩
gzip_min_length 1000; # 单位Byte
gzip_comp_level 5; # 压缩比,默认1,范围时1-9,值越大压缩比最大,但处理最慢,所以设置5左右比较合理。
}
2、配置请求头
underscores_in_headers
允许客户端请求在http请求中添加以下划线格式命名的参数
该字段可以放在http
指令模块
http {
underscores_in_headers on;
}
client_max_body_size
允许客户端上传文件最大不超过10M,在开发上传接口时一定要注意,否则导致上传失败
该字段可以放在http
、server
、location
指令模块
http {
client_max_body_size 10m;
}
3. 浏览器缓存配置
缓存也是前端优化的一个重点,合理的缓存可以提高用户访问速度
该字段可以放在http
、server
、location
指令模块。配置浏览器缓存的有三个地方
1)后端服务,配置请求头
后端根据语言不同,配置关键字段即可
2)代理服务器(Nginx)配置缓存请求头
location / {
# / 匹配到的资源有效期设置为1d
expires 1d;
# /设置资源有效期604800秒,即7天
# expires max-age=604800;
# 设置浏览器可以被缓存,设置7天后资源过期
add_header Cache-Control "public, max-age=604800";
# 阻止浏览器缓存动态内容
# add_header Cache-Control "no-cache, no-store, must-revalidate";
# 禁用浏览器缓存
# add_header Cache-Control "no-store, private, max-age=0";
}
我们发现响应头的过期时间更新了
3)在前端资源中通过meta声明缓存信息
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Expires" content="0">
4. 跨域处理
通过反向代理,已经处理了请求域名和端口不一致的跨域问题,但有局限性。 Nginx有专门方法配置请求资源的跨域
该字段可以放在server
、location
指令模块,通过配置头部字段,做跨域处理
server {
location / {
# 允许所有来源的跨域请求
add_header Access-Control-Allow-Origin *;
# 允许特定的HTTP方法(GET、POST等)
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
# 允许特定的HTTP请求头字段
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
# 响应预检请求的最大时间
add_header Access-Control-Max-Age 3600;
# 允许携带身份凭证(如Cookie)
add_header Access-Control-Allow-Credentials true;
# 处理 OPTIONS 预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
add_header Access-Control-Max-Age 3600;
add_header Access-Control-Allow-Credentials true;
add_header Content-Length 0;
add_header Content-Type text/plain;
return 204;
}
}
}
5. 访问控制
allow
、deny
控制 IP 允许和拒绝,字段可以放在server
、location
指令模块
server {
listen 80;
server_name example.com;
location /admin {
allow 192.168.1.0/24; # 允许特定 IP
deny all; # 拒绝所有其他访问
}
location /public {
# 允许所有访问
allow all;
}
location / {
deny all; # 拒绝所有其他访问
}
}