| title | Nginx | |
|---|---|---|
| date | 2018-12-15 04:05:09 -0800 | |
| tags |
|
|
| categories |
|
💠
-
- 4.1. 静态资源Web服务器
- 4.2. 4层转发 TCP/UDP
- 4.3. 反向代理多个服务
- 4.3.1. 静态资源+反代理后端
- 4.3.2. 前后端分离时避免跨域
- 4.4. 配置https
- 4.4.1. 自签发证书
- 4.4.2. 通过 certbot 配置 HTTPS
- 4.5. 配置Websocket反向代理
- 4.6. 代理-HTTP转发
- 4.7. 防盗链
- 4.8. gzip
- 4.9. 负载均衡
- 4.9.1. 负载均衡策略
- 4.10. SSE
💠 2025-11-24 22:27:23
- 安装
sudo apt install nginx - 启动服务
sudo nginx- 或者
sudo /etc/init.d/nginx start - 或者 systemd 方式
systemctl start nginx
- 或者
- 关闭
sudo nginx -s quit- 或者
sudo /etc/init.d/nginx stop - 或者 systemd 方式
systemctl stop nginx
- 或者
不建议使用这种方式进行安装,很容易出现兼容问题
- 下载 nginx,pcre,zlib,openssl 的压缩包
- 进入解压根目录(按实际情况配置)
配置各个包
./configure --sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-pcre=/home/kuang/pcre-8.20 \
--with-openssl=/home/kuang/openssl \
--with-zlib=/home/kuang/zlib-1.2.11-s signal- stop 停止
- quit 退出
- reopen 重新打开
- reload 重载配置(修改配置文件常使用)
-t测试配置文件
nginxWebUI
nginx-proxy-manager
0xJacky/nginx-ui: Yet another WebUI for Nginxgo+js
$remote_addr客户端地址$remote_port客户端端口
nginx 配置文件的语法是自己独有的语法, 比较像 shell, 里面有用到正则, 变量等概念
- 读取自定义目录配置:
- nginx.conf 中 http 块内添加
include /etc/nginx/conf.d/*.conf;
- nginx.conf 中 http 块内添加
- 错误页面重定向
error_page 404 /404.html;也可以填完整URL
nginx提供Http服务,但是反向代理了HTTPS地址时 需要注意证书的一致性问题
server {
client_max_body_size 4G;
listen 80;
# server_name static.me; # 如果需要使用域名 则需要在hosts文件配置
root /home/mini/Sync;
location / {
autoindex on; # 显示索引
autoindex_exact_size on; # 显示大小
autoindex_localtime on; # 显示时间
}
}- 若出现403错误, 将 /etc/nginx/nginx.conf 中第一行的
user nginx;改成可访问静态文件目录的用户即可 配置为文本文件类型即 text/plain; 类型。例: 浏览器直接查看 code 目录下所有源代码
location /code/ {
# All files in it
location ~* {
add_header Content-Type text/plain;
}
}如果有编码问题可配置成 add_header Content-Type 'text/plain;charset=UTF-8';
location ~* /.*\.(py|md|sql)${}
# 和 http 同级
stream {
upstream backend {
server 192.168.1.100:3306 weight=1;
server 192.168.1.101:3306 weight=1;
}
server {
listen 3306; # 对外暴露的 TCP 端口
proxy_pass backend; # 4 层转发
proxy_timeout 60s; # 下游连接超时
proxy_connect_timeout 10s; # 上游建连超时
so_keepalive on; # TCP 保活
}
}配置反向代理
- nginx 的 80 端口下:
/路径的请求转发到9991端口/myth转发到7898端口
upstream one {
server 127.0.0.1:9991;
}
upstream two {
server 127.0.0.1:7898;
}
server {
listen 80;
server_name 1.1.1.1;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxt true;
proxy_pass http://one;
proxy_redirect off;
}
location /myth{
proxy_pass http://two;
proxy_redirect off;
}
}配置统一出口
server {
client_max_body_size 4G;
listen 80; # listen for ipv4; this line is default and implied
server_name static.me;
location / {
root /data/static;
# proxy_pass http://127.0.0.1:8889/; 如果静态资源在别的端口上,这样配置也可以
}
location /api/ {
# add_header 'Access-Control-Allow-Origin' '*';
proxy_pass http://127.0.0.1:8889/; # 去除请求的 api 路径,并访问后端
# proxy_pass http://127.0.0.1:8889; 这种方式不会去除 /api/
}
location /api/a-service {
proxy_pass http://127.0.0.1:8889/a-service; # 移除 /api/ 路径,保留a-service (api路径下多个服务时使用此类型配置)
}
}- 将静态文件交由Nginx进行处理, 后台的服务统一用一个前缀和前台进行区分, 然后将服务端的真实host和ip或者域名配置进来
- 这样在于前端看来就是访问 static.me/api 而已, 实际上访问的是 127.0.0.1:8889/api
注意,原先使用nginx反向代理tomcat,尝试配置后端为一个本地dns解析的域名。然后发现这是无法生效的,所以应该使用真实IP或公网域名
在需要被跨域访问的服务端,添加如下配置
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST,OPTIONS; 如果使用caddy就会很简单,它会自动续签 lets crypt
配置HTTPS
upstream one {
server 127.0.0.1:8888;
}
server {
listen 443;
server_name web.me;
# 主要就是添加了这一块
ssl on;
ssl_certificate /data/https/server.crt;
ssl_certificate_key /data/https/server.key;
# http 转向 https
return 302 https://$host$request_uri;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxt true;
proxy_pass http://one; # 注意Nginx已经配置了SSL,后端只需支持http协议即可
proxy_redirect off;
}
}免费的网站, 并且现在支持泛域名了参考博客 | 参考博客
Nginx反向代理https
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
./certbot-auto #进行安装 但是过程中会有一些设置,
./certbot-auto certonly --email xxx@xxx --nginx -d xxx.domain # 生成 xxx.domain 证书SSL 接收到一个超出最大准许长度的记录 要在端口后加上SSL nginx
upstream one {
server 127.0.0.1:8080;
}
server{
listen 443 ssl;
server_name xxx.domain
access_log /data/log/https.log;
# ssl配置
ssl on;
ssl_certificate /etc/letsencrypt/live/xxx.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/xxx.domain/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/xxx.domain/chain.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
location / {
proxy_pass https://one;
}
} # 配置连接的配置信息
map $http_upgrade $connection_upgrade{
default upgrade;
'' close;
}
upstream back_end {
server 127.0.0.1:8888;
}
server {
listen 80;
server_name 127.0.0.1;
location / {
# 设置转发真实ip
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Nginx-Proxt true;
# 设置接收到的请求类型
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_pass http://back_end; # 末尾不能加任何uri
# 不设置的话 默认是 1.0 就会不支持 keepAlive
proxy_http_version 1.1;
proxy_redirect off;
proxy_read_timeout 300s; # 大于心跳时间即可
proxy_buffering off; # 关闭缓冲,实时帧,否则会出现ws消息业务意义上的粘包
proxy_cache off; # 禁用缓存
}
}- 如果没有按这里的配置,单纯做proxy_pass配置 会出现只有101状态码 只代表“握手”成功,但是没有建立 WS 帧隧道
- 可以通过在服务端执行 sudo tcpdump -i any -nn port 8888 来看是否有完整的握手和后续消息的tcp包
绕过Grafana,免密登录,需要预先生成key
map $http_upgrade $connection_upgrade{
default upgrade;
'' close;
}
# http://grafana-user.test/d/spring_boot_21/shang-shu-tai-jian-kong-mian-ban?orgId=1
server {
listen 80;
server_name grafana-user.test;
location / {
proxy_pass http://192.168.1.1:9091/;
proxy_redirect off;
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 Connection "";
proxy_set_header Authorization "Bearer xxxxx";
# add_header X-Frame-Options SAMEORIGIN;
proxy_hide_header X-Frame-Options;
}
location /api/live/ws {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-Nginx-Proxt true;
proxy_set_header Authorization "Bearer cccc";
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_http_version 1.1;
proxy_redirect off;
proxy_read_timeout 300s;
proxy_pass http://192.168.1.1:9091;
}
}例如 aaa.com 需要VPN等方式才能访问,Nginx所在的主机能访问,就可以这么配置,然后配置DNS将 aaa.com 解析到Nginx的主机上,就可以实现其他客户机不安装VPN 直接访问 aaa.com
server {
server_name aaa.com;
listen 80;
location / {
proxy_pass http://aaa.com;
proxy_set_header Host $host:$server_port;
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;
}
} gzip on;
gzip_comp_level 4; # 缺省值
gzip_buffers 4 16k;
gzip_http_version 1.1; # 缺省值
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
当前Nginx代理上游开启了gzip的服务,并解压其gzip响应
server {
server_name xxxx.cn;
location / {
proxy_set_header Accept-Encoding ""; # 禁用代理请求开启gzip
gzip off; # 禁用gzip
proxy_pass http://x.x.x.x:8080/;
}
}
遇到一个奇怪的问题:Nginx层开启gzip http的response的header里也有标识开启了gzip,但是body并没有被压缩,导致浏览器报错 ERR_CONTENT_DECODING_FAILED 无法解析response引发业务故障
分为四层和七层:
- 在四层只依据ip的报文转发(修改进入时目的ip
从nginx改成upstream的IP,修改返回时发送ip) - 在七层依据数据内容做转发,例如按http请求后缀做转发 *.jpg 到A服务器 *.jsp 到B服务器
- Round Robin:
- 默认方式,对所有backend无差别按序轮询, 如果backend宕机会自动移除掉
- Weight:
- 对所有backend按权重进行轮询,权重越高分发到的请求就越多,默认值为1。适合硬件差别比较大的多个节点
#动态服务器组 upstream dynamic_server { server localhost:8080 weight=2; server localhost:8081; server localhost:8082 backup; server localhost:8083 max_fails=3 fail_timeout=20s; }
- Least Connections(least_conn):
- 依据每个backend当前活跃连接数,将请求分发到连接数最少的backend上,此时会考虑backend的weight权重比例
- upstream配置块中在首行添加
least_conn;即可
- IP Hash(ip_hash): 对请求来源IP地址计算hash值,通过某种映射(例如取余,详细可查看ip_hash相关源码)分发至对应backend
- upstream配置块中在首行添加
ip_hash;即可
- upstream配置块中在首行添加
- Generic Hash(hash): 用户自定义资源(例如URL)计算hash完成分发,可选consistent关键字支持
一致性hash特性
Q & A
- 如果负载均衡了A B两个节点,请求进入了A节点后,立马移除了对A节点的负载均衡,该请求是否能正常执行
- 能正常执行,假如此时请求A失败,例如A节点宕机, 请求还会转移至B节点(failover)
- 如果负载均衡了A B两个节点, A节点宕机了,后续请求是否还会分发到A节点
- 不会,原理: TODO
由于http开启缓冲能提高内存使用率,但是这个设置和sse 消息流推送是违背的 否则会出现粘包拆包问题,需要关闭
proxy_set_header Connection '';
proxy_http_version 1.1;
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
# 关闭代理缓冲。当设置为off时,Nginx会立即将客户端请求发送到后端服务器,并立即将从后端服务器接收到的响应发送回客户端。
proxy_buffering off;
# 启用分块传输编码。分块传输编码允许服务器为动态生成的内容分块发送数据,而不需要预先知道内容的大小。
chunked_transfer_encoding on;
# 开启TCP_NOPUSH,这告诉Nginx在数据包发送到客户端之前,尽可能地发送数据。这通常在sendfile使用时配合使用,可以提高网络效率。
tcp_nopush on;
# 开启TCP_NODELAY,这告诉Nginx不延迟发送数据,立即发送小数据包。在某些情况下,这可以减少网络的延迟。
tcp_nodelay on;
# 设置保持连接的超时时间,这里设置为120秒。如果在这段时间内,客户端和服务器之间没有进一步的通信,连接将被关闭。
keepalive_timeout 120;对标 F5 BIG-IP
Keepalived软件起初是专为LVS负载均衡软件设计的,用来管理并监控LVS集群系统中各个服务节点的状态,后来又加入了可以实现高可用的VRRP功能。因此,Keepalived除了能够管理LVS软件外,还可以作为其他服务(例如:Nginx、Haproxy、MySQL等)的高可用解决方案软件。
具有丰富的插件支持, 配置简洁, 自动配置 HTTPS证书,相较于nginx资源消耗更多 吞吐量低一些
Official 企业级工具
Github
基于 HAProxy
- 文件上传报错 413
- http{} 中添加
client_max_body_size 80M;
- http{} 中添加
- request_time 比实际时间长 Nginx的延迟关闭
lingering_timeout
access 日志中 upstream 408状态码 本身返回的502 实际上upstream没收到请求