[快速入门]Nginx的配置
[快速入门]Nginx的配置
目标:
- 1、能快速阅读nginx配置文件,定位配置问题
- 2、能快速设置各种代理,快速解决工作中的环境问题+辅助未来的问题排查
1、nginx文件的层次结构
- 参考资料:https://www.cnblogs.com/54chensongxia/p/12938929.html
- 参考视频:https://www.bilibili.com/video/BV1mz4y1n7PQ/?spm_id_from=333.788.videopod.sections&vd_source=ea20f1fccee6fd3f1af7d59cd3ae7575&p=7

注意
我的理解:
除了【全局块】这个概念以外
nginx的配置文件中其他各种块都是含有{}
全局块-无{}
平时写的 nginx.conf,大概率是这样展开的:
注意
events {
}
http {
upstream {}
# 服务1
server {
listen== 80;
server_name *.whoway.xyz;
location / {
}
}
# 服务2
server {
listen 443 ssl http2;
server\_name whoway.xyz [www.whoway.xyz](http://www.whoway.xyz);
location / {}
}
}- 结论1:events配置是必备的!但是很容易配置
- 结论2:nginx配置最外层最常用的模块就是http 模块,从配置使用频率和心智模型上看,Nginx ≈ HTTP 配置系统
- 原因:HTTP 模块是 Nginx 最大、最成熟的一块
- http
- https(= http + ssl)【HTTPS / gRPC 本质仍然是 HTTP 语义:HTTP + TLS典型的配置个证书而已】
- grpc【HTTPS / gRPC 本质仍然是 HTTP 语义:HTTP/2 + protobuf】
- fastcgi【HTTP 作为前端协议】
- proxy
- uwsgi
- scgi
全部挂在 ngx_http_* 体系下,日常运维/开发 90+% 都在用 http
现实情况是:Web 服务、API 网关、反向代理、Ingress、服务网格边缘,全部是 HTTP 场景
结论3:另外日常不太常用的模块,但是云厂商大量用 stream** 模块**
stream 模块可以做TCP 反向代理、UDP 负载均衡、MySQL / Redis / Kafka / DNS、TLS passthrough(SNI)
2、设置变量+使用变量
使用:set:Nginx 的变量赋值指令,定义一个变量的值。
set $php_upstream 'unix:/home/work/myproject/php/var/php-cgi.sock';后边就能直接使用了,这个$php_upstream:自定义变量名,表示 PHP 请求转发的上游地址。
fastcgi_pass $php_upstream;3、服务名
server_name后边跟着的域名可以有多个,用空格隔开
server_name whoway.xyz www.whoway.xyz;4、location块中的:正则表达式
location块,Nginx中location指令的匹配操作符(如~、~*、^~、=等)的作用
Nginx的location指令匹配顺序是:
如果找到匹配项,Nginx将停止搜索并使用该
location块中的配置来处理请求!
- 首先检查
=精确匹配 - 然后检查
^~前缀匹配 - 接着按照配置文件中出现的顺序检查正则表达式匹配
- 最后检查无修饰符的前缀匹配。
| 匹配操作符 | 含义 | 示例 |
|---|---|---|
= | 精确匹配 | location = / { ... } |
^~ | 前缀匹配,**不使用正则**表达式 | location ^~ /images/ { ... } |
~ | 区分大小写的正则匹配 | location ~ \.php$ { ... } |
~* | 不区分大小写的正则匹配 | location ~* \.jpg$ { ... } |
无修饰符 | 前缀匹配 | location /documents/ { ... } |
5、反向代理+网关代理的对比
反向代理proxy_pass
介绍:127.0.0.1的80端口转发到127.0.0.1:8080. 在这里127.0.0.1就类似于服务器的ip地址同理。
server {
listen 80;
server_name localhost www.xxx.com; #域名
location / {
proxy_pass http://127.0.0.1:8080;
client_max_body_size 1024m; #请求体大小设置
}
}网关代理,以典型的:fastcgi_pass这个为例
CGI全称是“公共网关接口”(Common Gateway Interface),HTTP服务器与你的或其它机器上的程序进行“交谈”的一种工具,其程序一般运行在网络服务器上。 CGI可以用任何一种语言编写,只要这种语言具有标准输入、输出和环境变量。如php,perl,tcl等。
在互联网公司这种模式一般和php配合一起使用,php针对普通的CGI做了优化,一般主流使用fastcgi
【fastcgi 模块】参数意义
server {
listen 80;
server_name example.com;
root /var/www/html;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM配置
location ~ \.php$ {
# 安全设置:确保不处理不存在的PHP文件
try_files $uri =404;
# FastCGI参数
fastcgi_pass unix:/run/php/php8.1-fpm.sock; # 根据实际PHP版本修改
fastcgi_index index.php;
# 核心FastCGI参数
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
# 基础HTTP参数
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
# 包含默认的fastcgi_params文件(通常包含上述参数)
include fastcgi_params;
# 超时设置
fastcgi_read_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_connect_timeout 60s;
# 缓冲区设置
fastcgi_buffer_size 32k;
fastcgi_buffers 4 32k;
fastcgi_busy_buffers_size 64k;
}
}【必备1】
fastcgi_pass:这个命令是指定将http代理到哪个fastcgi服务端接口。fastcgi_pass后面是填写fastcgi服务端地址的,这个地址可以是host和port,也可以是Uninx-域套接字。unix域套接字:
unix:/tmp/php-cgi.sock;'unix:/home/work/odp/php/var/php-cgi.sock':表示通过 Unix Socket 方式连接 PHP-FPM 进程,路径指向 PHP-FPM 监听的 sock 文件。
host和port:
127.0.0.1:9000;#指定监听的地址和端口号【是fpm服务监听的地址和端口】
【必备2】
fastcgi_index:fastcgi默认的主页资源比如:
fastcgi_index index.php;- 这个功能和http的那种
index index.html功能一样,当SCRIPT_FILENAME没有命中脚本的时候,使用的就是fastcgi_index设置的脚本。
- 这个功能和http的那种
【必备3】fastcgi_connect_timeout:nginx与后端fastcgi server连接超时时间
【必备4】fastcgi_send_timeout:nginx向后端传送请求超时时间(指已完成两次握手后向fastcgi传送请求超时时间)。
【必备】fastcgi_read_timeout:nginx接受后端fastcgi响应请求超时时间
【必备】fastcgi_param:这个命令是设置 fastcgi 请求中的参数,具体设置的东西可以在 PHP 的
$_SERVER中获取到主要完成的工作是将 Nginx 中的变量翻译成 PHP 中能够理解的变量!
这些参数是PHP应用中获取请求信息的基础,框架如Laravel、ThinkPHP内部也是通过这些变量工作的。
举个php读取$_SERVER变量
<?php
// 获取一些 $_SERVER 变量
echo "=== FastCGI 参数示例 ===\n\n";
// 1. 基础路径信息
echo "SCRIPT_FILENAME: " . ($_SERVER['SCRIPT_FILENAME'] ?? '未设置') . "\n";
echo "DOCUMENT_ROOT: " . ($_SERVER['DOCUMENT_ROOT'] ?? '未设置') . "\n";
echo "REQUEST_URI: " . ($_SERVER['REQUEST_URI'] ?? '未设置') . "\n";
echo "SCRIPT_NAME: " . ($_SERVER['SCRIPT_NAME'] ?? '未设置') . "\n";
// 2. 请求信息
echo "\n=== 请求信息 ===\n";
echo "REQUEST_METHOD: " . ($_SERVER['REQUEST_METHOD'] ?? '未设置') . "\n";
echo "QUERY_STRING: " . ($_SERVER['QUERY_STRING'] ?? '未设置') . "\n";
echo "REQUEST_SCHEME: " . ($_SERVER['REQUEST_SCHEME'] ?? '未设置') . "\n";
// 客户端信息
echo "\n=== 客户端信息 ===\n";
echo "REMOTE_ADDR (客户端IP): " . ($_SERVER['REMOTE_ADDR'] ?? '未设置') . "\n";
echo "REMOTE_PORT: " . ($_SERVER['REMOTE_PORT'] ?? '未设置') . "\n";
echo "HTTP_USER_AGENT: " . ($_SERVER['HTTP_USER_AGENT'] ?? '未设置') . "\n";典型的
| Nginx配置 | PHP中读取 | 用途 |
|---|---|---|
SCRIPT_FILENAME | $_SERVER['SCRIPT_FILENAME'] | PHP脚本的完整路径 |
REQUEST_URI | $_SERVER['REQUEST_URI'] | 请求的URI(含参数) |
QUERY_STRING | $_SERVER['QUERY_STRING'] | 查询字符串 |
REMOTE_ADDR | $_SERVER['REMOTE_ADDR'] | 客户端IP |
REQUEST_METHOD | $_SERVER['REQUEST_METHOD'] | 请求方法 |
HTTP_USER_AGENT | $_SERVER['HTTP_USER_AGENT'] | 浏览器信息 |
参考资料:Nginx 之 fastcgi 常用参数详解:https://blog.csdn.net/weixin_43844718/article/details/127027017
场景1:配置1个HTTPS站点,指定TLS证书
- 无论静态or动态站点
这种部署方式由 Nginx 服务器负责 SSL 请求的运算,相对减轻了后端上游服务器的 CPU 运算量。
# 一个HTTPS站点
server {
listen 443 ssl;
server_name demo.whoway.xyz;
ssl_certificate /etc/ssl/certimate/fullchain.pem; #RSA证书
ssl_certificate_key /etc/ssl/certimate/privkey.pem; #RSA密钥
ssl_protocols TLSv1.2 TLSv1.3;
# 配置加密套件/加密算法,写法遵循 openssl 标准。
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
# 禁用 OCSP stapling
ssl_stapling off;
ssl_stapling_verify off;
# 启用会话缓存可以提高性能
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://127.0.0.1:8090/;
# 传递真实 IP 和主机信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}场景2:动态网站,配置跨域
跨域(CORS)问题是浏览器安全机制导致的,后端需要在响应头里添加:
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials这些都可以通过 Nginx 在响应头里加上。
假设你在 Nginx 里有个 API 接口
server {
listen 80;
server_name api.example.com;
# 这个/的没加跨域
location / {
root /var/www/html;
index index.html;
}
# 所有 /api/ 路径下的接口都允许跨域
location /api/ {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
# 对预检请求(OPTIONS)立即返回204
if ($request_method = OPTIONS) {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';
add_header 'Access-Control-Max-Age' 3600;
# HTTP 204 No Content 成功状态响应码,表示该请求已经成功了,但是客户端客户不需要离开当前页面。
# 默认情况下 204 响应是可缓存的
return 204;
}
# proxy_pass 是 Nginx 反向代理(reverse proxy) 的核心指令
# 也是跨域配置里最常一起用的。
# 把客户端请求转发到后端服务器,然后把后端响应返回给前端。
# 意思是:浏览器访问 http://api.example.com/api/test
# Nginx 会转发到 http://127.0.0.1:8080/api/test
proxy_pass http://127.0.0.1:8080;
}
}场景3:静态网站
为了加快网站解析速度,可以将动态资源交给后端服务器,纯前端的静态页面放在系统目录下,交给Nginx来解析。
server {
listen 80;
server_name localhost;
location / {
root /opt/nginx/html;
index index.html index.htm;
}
}index指令
当用户访问网站根路径 /
按顺序尝试返回这些文件:
- 如果 index.html 和 index.htm 都存在, 那 nginx 会按照配置里的 顺序优先 来选择。
index.html是常见的首页文件。index.htm只是为了兼容旧系统或旧习惯(早期 Windows/IIS 会生成.htm后缀)。
场景5:配置fastcgi
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000; #指定监听的地址和幽口号【是fpm服务监听的地址和端口】
fastcgi_index index.php;
#指明当前fpm服务的root路径
#如,请求http://localhost/index.php
#就会对应这个选项中定义的/usr/local/nginx/html/index.php文件路径
fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;
include fastcgi_params;
}场景3:限速
下载限速:限制现在速度及并发连接数,应用在下载服务器中,保护带宽及服务器的IO资源。
请求限速:限制单位时间内用户访问请求,防止恶意攻击,保护服务器及资源安全。
Nginx官方版本限制IP的连接和并发分别有两个模块:
limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 "leaky bucket"。
limit_req_conn 用来限制同一时间连接数,即并发限制。限制客户端请求”== 指的是 ==限制请求频率 / QPS / 并发数
在 Nginx 里是 limit_req + limit_conn 的典型用法。
http {
# $binary_remote_addr 客户端 IP(二进制,省内存)
# 1r/s每秒 1 个请求
# zone=req_limit_per_ip:10m 共享内存区,存放限流状态
# 按客户端 IP 作为限流 key
limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=1r/s;
server {
listen 80;
server_name localhost;
location /req {
# 启用限流
# burst=2 允许瞬时突发 2 个请求
# nodelay突发请求不延迟,直接放行 不加 nodelay 超出 rate 的请求会被“排队”
limit_req zone=req_limit_per_ip burst=2 nodelay;
return 200 "request ok\n";
}
}
}测试为
for i in {1..5}; do curl http://localhost/req; done==限制并发连接数 —— ==limit_conn
比如:限制:每个 IP 同时最多 1 个连接
什么时候用 limit_conn ?
防止:
- 慢连接攻击
- 大量 keepalive 占连接
下载、长连接接口
http {
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;
server {
listen 80;
location /conn {
limit_conn conn_limit_per_ip 1;
return 200 "connection ok\n";
}
}
}限制下载速度limit_rate【没想到好的用途】
server {
listen 80;
server_name localhost;
location /rate {
# 下载限速:1KB/s
limit_rate 1k;
default_type text/plain;
return 200
'==================== RATE LIMIT DEMO =====
==========================================================
';
}
}场景4:防盗链
百度百科定义:盗链是指服务提供商自己不提供服务的内容,通过技术手段绕过其它有利益的最终用户界面(如广告),直接在自己的网站上向最终用户提供其它服务提供商的服务内容,骗取最终用户的浏览和点击率。受益者不提供资源或提供很少的资源,而真正的服务提供商却得不到任何的收益。盗资源是黑产界以最小成本获取最高利益的一个常用手段。
通常站点,都会想让自己网站的视频和图片,免被盗用,毕竟流量,花的都是自己的钱。
1、【防不了一点】一般的 Nginx 防盗链手段都是**
通过 referer 字段来判断请求的来源地,由此去判定请求是否合法**。但是该字段容易伪造,所以很少用该方法实现防盗功能。原理:Referer 是 Header 的一部分,当浏览器向 Web 服务器发送请求的时候,一般会带上 Referer,告诉服务器该请求是从哪个页面链接过来的,服务器就可以禁止或允许某些来源的网站访问资源。2、而Nginx 的 secure_link 模块主要是使用 hash 算法加密方式,一般用于图片、视频下载,生成下载 URL,安全性高。
3、也可以使用一些第三方的模块增强 Nginx 的防盗链功能,比如常用的第三放模块ngx_http_accesskey_module 可用于实现文件下载的防盗功能
没有配置防盗链的情况下,放开静态资源的访问,是这样的配置
location ~* .*\.(gif|jpg|ico|png|css|svg|js)$ {
root /usr/local/nginx/static;
}附录1、Nginx的CGI相关
理解nginx的proxy_pass和fastcgi_pass的区别和联系,就能理解为什么C和go也能类似php一样被代理了
我的理解
- 我们可以使用fastcgi_pass网关代理,和网关程序去交互!
- 也可以使用proxy_pass反向代理去和另一个服务器交互【比如tomcat、apache、还有go的gin框架写的服务器监听或者python写的WSGI监听?
- 我觉得:fastcgi_pass只是一个反向代理的一个特殊子集!proxy_pass才是最主要的、核心的!任何fastcgi_pass啥的,我觉得都能通过proxy_pass解决!
nginx配置fastcgi、scgi、uwsgi
这里面可以看到,指定请求方法名、指定请求协议、增改请求头部、设置请求包体这四类 uwsgi、fastcgi、scgi 是不需要这样的应用的,HTTP 则支持修改方法名、协议、头部和包体设置。
| 【常用】http 反向代理 | 【常用】fastcgi 反向代理 | uwsgi 反向代理 | scgi 反向代理 | |
|---|---|---|---|---|
| 指定上游 | proxy_pass | fastcgi_pass | uwsgi_pass | scgi_pass |
| 是否传递请求头部 | proxy_pass_request_headers | fastcgi_pass_request_headers | uwsgi_pass_request_headers | scgi_pass_request_headers |
| 是否传递请求包体 | proxy_pass_request_body | fastcgi_pass_request_body | uwsgi_pass_request_body | scgi_pass_request_body |
| 指定请求方法名 | proxy_method | |||
| 指定请求协议 | proxy_http_version | |||
| 增、改请求头部 | proxy_set_header | |||
| 设置请求包体 | proxy_set_body | |||
| 是否缓存请求包体 | proxy_request_buffering | fastcgi_request_buffering | uwsgi_request_buffering | scgi_request_buffering |
附录2、Nginx典型PHP的fastcgi
使用nginx和php交互,理解大公司内部,相关php的处理
FastCGI是从CGI发展改进而来的。
传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务器。
这在处理高并发访问时,几乎是不可用的。另外传统的CGI接口方式安全性也很差,现在已经很少被使用了。
FastCGI接口方式
1、采用C/S结构,可以将HTTP服务器和脚本解析服务器分开
2、同时在脚本解析服务器上启动一个或者多个脚本解析守护进程。
3、当HTTP服务器每次遇到动态程序时,可以将其直接交付给FastCGI进程来执行,然后将得到的结果返回给浏览器。
这种方式可以让HTTP服务器专一地处理静态请求或者将动态脚本服务器的结果返回给客户端,这在很大程度上提高了整个应用系统的性能。
附录3、nginx可以做的一些优化配置
nginx优化之keepalive
当使用nginx作为反向代理时,为了支持长连接,需要做到两点:
从client到nginx的连接是长连接
从nginx到server的连接是长连接
附录4、【进阶】nginx的stream模块,只有做负载均衡之类去看
L4是
stream== 模块是以 L4 为核心、少量感知 L7 信号的代理==
L4(核心工作层)
这是 stream 的绝对主战场:
- TCP / UDP
- 端口
- 连接生命周期
- 四元组(src/dst IP + port)
- 连接数 / 超时
它“少量感知 L7”?
比如TLS SNI(ssl_preread)
map $ssl_preread_server_name $backend {
a.com backend1;
b.com backend2;
}
- 解析 TLS ClientHello
- 读取 SNI
- 不解密、不处理 HTTP
这是 L7 信息,但只“窥探”不“处理”
云厂商 SLB / NLB
- 四层转发
- 不碰 HTTP
- 不关心备案
- 责任下沉到客户
K8s Ingress TLS 透传
- 只看端口 / SNI
- 不解 HTTP
- 性能极高
数据库代理
- MySQL / Redis
- 完全是 TCP