一、概述
Nginx一个具有高性能的【HTTP】和【反向代理】的【WEB服务器】,同时也是一个电子邮件代理服务器。正向代理服务的是客户端(比如VPN),反向代理服务的是服务端。Nginx是多进程的,有一个Master进程控制多个Worker进程。速度快、并发高、热部署。
1、优点
- 速度快,并发高,在5万左右。采用多进程,io多路复用技术。像Tomcat是一个重量级的服务器,并发在200左右
- 配置简单,扩展性强
- 高可靠性,有master进程和worker进程,其中master进行单独用于管理worker进程
- 热部署
- 成本低,BSD许可证(可以修改源码并且可以用来赚钱)
2、常用模块
- 静态资源部署
- Rewrite地址重写,使用正则表达式
- 反向代理
- 负载均衡
- web缓存
- 用户认证模块
3、核心组成
- nginx:二进制可执行文件
- nginx.conf:核心配置文件
- error.log:错误的日志记录
- access.log:访问日志记录
- nginx.pid:记录nginx的Master进程id
二、配置
# nginx.config文件
# 全局配置部分
#-----------------------------
# 定义工作进程数量(建议设置为CPU核心数或自动检测)
# 值:数字 或 auto
worker_processes 4;
# user指令:用于配置运行Nginx服务器的worker进程的用户和用户组。使用user指令启动的时候,可以指定Linux系统的用户和用户组,然后访问Nginx的时候,只能访问到该用户拥有权限的目录,进行权限访问控制。
# daemon:是否已守护进程运行,默认为on
# pid:用于指定存放master进程id的文件路径
# error_log:用于配置Nginx错误日志存放的路径
# include:可以引入其他的配置文件,可以放在任何位置,放在全局块中可以引入全局块指令
# 事件模块配置(控制连接处理模型)
#-----------------------------
events {
# 每个Worker进程允许的最大并发连接数(包含活动连接和空闲连接)。默认 512。设置值不能超过操作系统支持打开的最大句柄数量
# 总最大连接数 = worker_processes * worker_connections
worker_connections 40960;
# accept_mutex:用来设置Nginx网络连接序列化,默认为on。用来解决惊群问题,就是一个请求发送过来,所有的worker进程都会唤醒来抢夺这个请求,设置为on开启序列化,意为每次来请求,只会唤醒一个worker进程来处理请求。根据实际需求来配置,因为可能会同时发送过来多个请求
# muli accept:用来设置是否允许woker进行同时接受多个网络连接。默认为off,可以打开提高速度
# use:设置Nginx服务器使用哪种事件驱动来处理网络消息。默认值根据操作系统来确定。推荐使用epoll使用io多路复用。
}
# HTTP核心模块配置
#-----------------------------
http {
# 根据User-Agent判断设备类型(用于后续条件判断)
# 定义变量 $device_type,默认值为desktop,匹配移动设备则设为mobile
map $http_user_agent $device_type {
default desktop; # 默认值
~*android|iphone|ipad|ipod mobile; # 正则匹配(不区分大小写)
}
# 包含MIME类型定义文件(默认路径为nginx目录下的conf/mime.types)
# 我们都知道浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME Type。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型。default_type 来指定相应给前端的类型, application/octet-stream会下载下来响应
include mime.types;
# access_log:用来设置用户访问日志的目录、格式等相关属性
# log_format:用来指定日志的输出格式
# 默认响应类型(当无法识别文件类型时使用)
# 注意:application/wasm 是WebAssembly的MIME类型,需确认是否需要此设置
default_type application/wasm;
# 启用高效文件传输模式(零拷贝技术)。用来设置Nginx服务器是否使用Linux操作系统的sendfile()传输文件,该属性可以大大提高Nginx处理静态资源的性能。默认off
# 读取文件流程是客户端请求,用户区、内核区、磁盘、网卡中进行多次拷贝,效率较低,四次拷贝,sendfile是操作系统底层函数。开启可以提升效率,不需要多次拷贝,可以指定读取到哪个socket,直接响应给客户端。服务端的数据要返回给客户端。那么有两种模式,一种是实时发送,即`tcp_nodelay`,默认on,来了一个数据就直接发送给客户端,这样实时性很高,但是消耗性能。第二种就是开辟一个缓冲区,即`tcp_nopush`,默认off,依赖sendfile,数据将缓冲区填满之后再一起发送,实时性弱一点,但是性能高。两个配置看起来是互斥的,但是Linux2.5.9之后进行了优化,所有建议三者都打开,配置在http块。
sendfile on;
# 客户端保持连接的超时时间(单位:秒)。用来设置长连接的超时时间。如何客户端向服务端发送多个请求,每个请求都需要重新创建一次连接,效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。默75秒
keepalive_timeout 65;
# keepalive_requests:用来设置一个keep-alive连接使用的次数,达到次数就关闭这个连接
# 从ISO8601时间格式中提取日期(用于日志文件名)
map $time_iso8601 $logdate {
'~^(?<ymd>\d{4}-\d{2}-\d{2})' $ymd; # 正则捕获年月日
default 'date-not-found'; # 匹配失败时的默认值
}
# 访问日志配置(按日期分割日志)
access_log logs/access-$logdate.log;
# 客户端请求相关配置
#-----------------------------
client_max_body_size 50m; # 允许客户端上传的最大文件大小(重要!涉及文件上传需设置)
client_body_buffer_size 60k; # 客户端请求体缓冲区大小
client_body_timeout 60; # 客户端请求体读取超时时间(秒)
client_header_buffer_size 64k; # 客户端请求头缓冲区大小
client_header_timeout 60; # 客户端请求头读取超时时间(秒)
# 错误页面配置
#-----------------------------
error_page 400 /error/400.html; # 错误码映射到指定URI
error_page 403 /error/403.html;
error_page 404 /error/404.html;
error_page 500 /error/500.html;
# ...(其他错误码配置,需确保/error目录下存在对应HTML文件)
# 高级连接配置
#-----------------------------
keepalive_requests 1000; # 单个Keep-Alive连接允许的最大请求数
large_client_header_buffers 4 64k; # 大型请求头的缓冲区数量和大小
reset_timedout_connection on; # 关闭超时未响应的连接以释放资源
send_timeout 60; # 响应发送超时时间(秒)
# 文件传输优化
sendfile_max_chunk 512k; # 单次sendfile调用的最大传输量(避免Worker进程阻塞)
# 服务器名哈希表优化
server_names_hash_bucket_size 256; # 服务器名哈希表桶大小(域名较长时需要增加)
# 包含虚拟主机配置文件(通常用于分站点管理)
include vhosts/*.conf;
}
# 系统资源限制(需放在全局块,不能放在http块内)
#-----------------------------
worker_rlimit_nofile 100000; # Worker进程能打开的最大文件描述符数量(需配合系统ulimit设置)
# includ.config文件
# ======================================================
# Nginx Server 块配置详解
# 此配置用于处理域名为 dbgmarkets.co 的 HTTP/HTTPS 请求
# 实现功能:SSL 加密、动静分离、API 代理、设备类型适配、Gzip 压缩
# ======================================================
# server块的匹配优先级是:准确匹配、通配符在前的匹配、通配符在后的匹配、正则表达式的匹配、默认的server匹配
server {
# --------------------------
# 监听端口与协议配置
# --------------------------
listen 80; # 监听 IPv4 的 HTTP 80 端口
listen 443 ssl http2 default_server; # 监听 IPv4 的 HTTPS 443 端口,启用 HTTP/2,设为默认主机
listen [::]:443 ssl http2 default_server; # 监听 IPv6 的 HTTPS 443 端口
# 说明:
# - default_server: 当请求未匹配其他 server_name 时,并且请求的为指定监听的端口,则由此块处理。没有指定默认server,第一个server就是默认的server
# - http2: 启用 HTTP/2 协议提升性能
# - ssl: 启用 SSL/TLS 加密
# --------------------------
# 域名与基础设置
# --------------------------
server_name dbgmarkets.co; # 匹配的域名(精确匹配,不含 www 等子域名)。用于指定访问的ip或域名。多个域名间用空格分隔。有三种模式,精确匹配,通配符*匹配(不能写在中间,只能出现在首段和尾端,否者会失效),正则表达式匹配(必须使用~作为开始标识)。其中正则表达式,可以使用括号和$N方式在return中获取对应访问的值
absolute_redirect off; # 关闭绝对路径重定向(返回相对路径,适用于反向代理后方场景)
# --------------------------
# Gzip 压缩配置(优化传输效率)
# --------------------------
# 在http块中。gzip设置为on。gzip_types 设置要压缩的类型,默认只会压缩text/html类型。
# gzip_comp_level:有1到9个级别。1压缩最快,压缩程度低,建议设置为6,基本已经极限。
# gzip_vary:默认off。开启之后,会在响应头上面添加Vary:Accept-Encoding
# gzip_buffers number size:设置压缩时缓冲区的数量和大小。默认即可
# gzip_disable "正则表达式" : 会匹配浏览器的user-agnet,匹配到的就不进行压缩
# gzip_min_length:当资源小于这个指定大小后,就不进行压缩了。默认20b
# gzip_proxied:默认off。指的是作为反向代理服务器,对于后端返回的数据是否进行压缩。
# gzip_static:默认off这个是在还没有读取时就压缩文件,然后直接读取对应文件的.gz文件,有的话就直接使用这个文件,没有的话在读取源文件,使用头信息Content-Encoding:gzip和Vary:Accept-Encoding告诉浏览器进行了文件压缩。
gzip on; # 启用 Gzip 压缩
gzip_min_length 1k; # 只压缩大于 1KB 的文件
gzip_comp_level 9; # 压缩级别 1-9(9 最高压缩率,CPU 消耗较大)
gzip_types text/plain text/css text/javascript application/json application/javascript application/x-javascript application/xml; # 压缩指定 MIME 类型
gzip_vary on; # 添加 "Vary: Accept-Encoding" 头
gzip_disable "MSIE [1-6]\."; # 为旧版 IE 浏览器禁用压缩
# --------------------------
# SSL/TLS 安全配置
# --------------------------
ssl_certificate C:/crm/nginx-1.20.2/ssl/dbgmarkets_co/dbgmarkets_co.crt; # SSL 证书路径(Windows 格式)
ssl_certificate_key C:/crm/nginx-1.20.2/ssl/dbgmarkets_co/dbgmarkets_co.key; # SSL 私钥路径
ssl_session_cache shared:SSL:1m; # SSL 会话缓存(1MB 内存,减少握手开销)
ssl_session_timeout 10m; # SSL 会话超时时间(10 分钟)
ssl_ciphers HIGH:!aNULL:!MD5; # 加密套件配置(HIGH 安全级别,禁用 aNULL/MD5)
ssl_prefer_server_ciphers on; # 优先使用服务端加密套件
# 注意:建议添加 ssl_protocols TLSv1.2 TLSv1.3; 以禁用老旧协议
# --------------------------
# 静态资源服务配置
# --------------------------
# root 实际返回的资源是root路径+location路径
# alias 实际返回的资源只是alias的路径
root C:/crm/web/dist; # 静态文件根目录(前端构建产物存放路径)
# 示例:请求 /css/style.css 将映射到 C:/crm/web/dist/css/style.css
# --------------------------
# 公共代理头设置
# --------------------------
proxy_set_header X-Forwarded-Proto $scheme; # 传递客户端协议(http/https)
proxy_set_header X-Real-IP $remote_addr; # 传递客户端真实 IP
client_max_body_size 15M; # 允许客户端上传最大 15MB 文件(如文件上传功能)
# --------------------------
# 路由处理:根路径(/)
# --------------------------
location / {
# 设备类型判断(根据全局 map 映射的 $device_type 变量)
if ($device_type = mobile) { # 如果是移动设备
proxy_pass http://127.0.0.1:3001; # 代理到本地的 3001 端口(移动端服务)
break; # 终止后续处理
}
index index.html; # 默认访问文件
try_files $uri $uri/ /index.html; # 前端 SPA 路由支持(找不到文件时返回 index.html)
# 流程:尝试访问真实文件 → 查找目录 → 回退到 index.html
}
# --------------------------
# 路由处理:API 接口(/api)
# --------------------------
# location /api 匹配所有以/api开头的请求
# =/api 精确匹配,只匹配/api的请求
# ~^/api\w$ 正则表达式匹配,~标识使用正则表达式,^开头,$结尾。其中使用~*标识正则表达式不区分大小写
# ^~/api 匹配第一个以/api开头的请求。默认的匹配顺序是匹配所有的条件,返回最后一个匹配到的,这个^~标识表示匹配到这个表达式之后,就不再向后匹配,直接返回结果
location /api {
# 解决跨域问题
# add_header Access-Control-Allow-Origin 访问的ip地址端口号
# add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE
# 代理到本地的 81 端口(后端 API 服务)
proxy_pass http://127.0.0.1:81;
# 关键代理头设置
# WebSocket 协议升级支持
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host; # 传递原始域名
# 补充:通常还需添加 X-Forwarded-For 头记录客户端 IP 链
}
# --------------------------
# 错误页面配置
# --------------------------
# 5xx 错误统一返回 50x.html。error_page 500 =200 /error.html 使用=可以将返回的状态码500改为200
error_page 500 502 503 504 /50x.html;
# 注意:需确保 root 目录存在 50x.html 文件
}
# rewrit 指令
# set指令。`set $key value`。设置变量键值对。$key可以直接使用。Nginx有预定的变量,如$args就是所有请求参数,$host获取到的是访问的服务器地址
# `if (){}`指令。条件如果是一个变量,不为空或0就是true。也可以使用=和!=判断,不需要引号。也可以使用正则表达式判断,变量和表达式之间用空格和~隔开,然后匹配上为true,其中~区分大小写,~*不区分大小写,!~表示取反。还可以使用内置参数和变量结合判断,如`-f $request_filename`用来判断这个文件是否存在。
# break;指令,终止当前作用域,并且会重定向到当前indx文件。
# `rewrite 正则表达式 地址 [命令]`。命令:last:匹配到后会拿这个地址去所有块中寻找,然后转发;break:匹配到后,会拿这个地址去本块中寻找;redirect:重定向到指定地址,临时重定向302;permanent:永久重定向,301
# `rewrite_log on;`开启后,会以notice级别输出到error日志中。所以需要 `error_log error.log notice;`
# `return code url`:直接返回指定的code,跳转到对应的url上。