本文参考 nginx一小时入门精讲课程(干货纯享版)_哔哩哔哩_bilibili 和 【狂神说】Nginx最新教程通俗易懂,40分钟搞定!_哔哩哔哩_bilibili
正向代理和反向代理
正向代理(Forward Proxy)
- 功能:在客户端代理转发请求称为正向代理,比如 VPN。
- 用途:常用于网络加速、匿名访问等。 客户端通过正向代理访问外部资源。 正向代理:从客户端的角度出发,客户端向正向代理服务器发出请求,正向代理服务器再将请求转发到目标服务器,接收到响应后再将其返回给客户端。 隐藏的是客户端,目标服务器并不知道客户端的真实IP地址。
反向代理(Reverse Proxy)
- 功能:反向代理代理的是服务器。外部客户端通过反向代理访问后端的服务器。反向代理会将请求分发到合适的服务器上,从而隐藏服务器的真实IP并提高安全性。
- 用途:常用于负载均衡、安全防护、缓存加速等。
从服务器的角度出发,外部客户端的请求先到达反向代理服务器,反向代理服务器根据请求内容,将其转发给内部合适的服务器,然后将服务器的响应返回给客户端。
隐藏的是服务器,客户端并不知道请求的最终服务器是哪一台。
类别 | 正向代理(Forward Proxy) | 反向代理(Reverse Proxy) |
---|---|---|
功能 | 代理客户端访问外部资源,隐藏客户端的真实 IP | 代理外部请求访问内部服务器,隐藏服务器的真实 IP |
用途 | 网络加速、匿名访问、绕过访问限制 | 负载均衡、安全防护、缓存加速 |
工作方向 | 从客户端发出请求,经正向代理到达目标服务器,再返回客户端 | 从外部请求到达反向代理,代理分发给内部服务器,再返回客户端 |
隐藏对象 | 隐藏客户端的真实 IP | 隐藏服务器的真实 IP |
配置位置 | 配置在客户端所在网络内 | 配置在服务器所在网络前端 |
典型场景 | 访问受限网站、浏览器代理配置 | 负载均衡、CDN、提高服务器安全性 |
动静分离
通过 Nginx 配置文件,将动态内容和静态内容分开处理,以提高性能和安全性。Nginx 作为一个高性能的 HTTP 服务器和反向代理服务器,可以很容易地实现动静分离。
原理
- 静态内容:通常包括 HTML、CSS、JavaScript 文件、图片等不需要服务器处理的文件,可以直接由 Nginx 提供服务。Nginx 直接读取这些文件并返回给客户端。
- 动态内容:通常由后端应用服务器(如 PHP、Python、Node.js)生成,Nginx 将这些请求转发给后端服务器进行处理,然后将处理结果返回给客户端。
好处
- 性能优化:静态内容直接由 Nginx 提供,减少了后端服务器的压力,提高了响应速度。
- 安全性提升:后端应用服务器不直接暴露在外网,减少了攻击面,增强了安全性。
- 更好的可维护性:静态资源和动态内容可以独立更新和管理。
Nginx 动静分离配置示例
假设你的静态文件放在 /var/www/static
目录中,API 请求以 /api/
为前缀,通过 Nginx 转发给后端应用服务器。
|
|
配置说明
静态文件的处理:
root /var/www/static;
:设置静态文件根目录。index index.html;
:指定默认的首页文件。try_files $uri $uri/ /index.html;
:如果请求的 URI 不存在,重定向到index.html
,通常用于单页应用(SPA),这样可以让前端路由正确处理页面导航。
API 请求的处理:
location /api/
:将所有以/api/
开头的请求转发给后端服务器(如 Node. js、Python 等)。proxy_set_header
:设置请求头信息,如Host
、客户端 IP 地址等,以确保后端服务器可以正确处理请求。
/images/1.jpg
代理到 http://localhost:8080/images/1.jpg
/some/path/1.jpg
代理到http://localhost:8080/some/path/1.jpg
WebSocket 请求的处理(可选):
location /ws/
:用于处理 WebSocket 请求,常见于实时通信应用。proxy_http_version 1.1
和proxy_set_header Upgrade $http_upgrade;
:确保支持 WebSocket 升级。
错误页面处理:
error_page 404 /404.html;
:自定义 404 错误页面。location = /404.html
:指定错误页面的路径和静态资源目录。
location 修饰符
●location 可以使用修饰符或正则表达式
修饰符:
|
|
- = 等于,严格匹配,匹配优先级最高。
^~
表示普通字符匹配。使用前缀匹配。如果匹配成功,则不再匹配其它 location。优先级第二高。~
区分大小写~*
不区分大小写
●优先级
优先级从高到低依次为:。
- 精确匹配(=)
- 前缀匹配(^~)
- 正则匹配(~ 和~*)
- 不写
负载均衡
基本原理
Nginx 负载均衡的基本工作原理是接受客户端的请求,并将这些请求分发给一组后端服务器(称为上游服务器)。Nginx 可以根据不同的负载均衡算法来选择将请求转发给哪个后端服务器。
常见的负载均衡算法
Nginx 支持多种负载均衡算法,常见的有以下几种:
轮询(Round Robin):
- 默认的负载均衡算法,Nginx 会按顺序将请求依次分发给后端服务器。所有服务器的权重相等。
最少连接(Least Connections):
- 将请求分发给当前连接数最少的服务器,这种算法适用于后端服务器负载不均衡的情况。
IP 哈希(IP Hash):
- 通过客户端 IP 的哈希值来决定将请求分发到哪个服务器,这种方式可以确保同一客户端的请求总是被分发到同一台服务器上,适用于需要会话保持的场景。
权重(Weight):
- 为后端服务器配置不同的权重,权重越高的服务器收到的请求越多,适用于后端服务器性能不一致的情况。
配置 Nginx 负载均衡
以下是一个 Nginx 负载均衡的配置示例:
|
|
配置说明
upstream
块:- 定义了一个叫做
backend
的上游服务器组。 - 组内包含三个服务器:
backend1.example.com
、backend2.example.com
和backend3.example.com
。 weight=3
表示backend1
的权重是 3,接收的请求数量是backend2
和backend3
的三倍。
- 定义了一个叫做
server
块:- 配置了一个监听
80
端口的虚拟主机,并且处理example.com
域名的请求。 location /
配置中使用proxy_pass http://backend
将所有请求转发到upstream backend
定义的服务器组。
- 配置了一个监听
proxy_set_header
指令:- 这些指令用于设置转发请求时的请求头信息,如客户端的真实 IP 地址、原始请求的 Host 等。
负载均衡算法配置
轮循机制(round-robin)
默认机制,以轮循机制方式分发。
最少连接算法(least-connected )
|
|
请注意,使用轮循机制或最少连接的负载平衡,每个客户端的请求都可能分发到不同的服务器。不能保证同一客户端将始终定向到同一服务器。
IP-hash
|
|
此方法可确保来自同一客户端的请求将始终定向到同一服务器,除非此服务器不可用。
Hash
通用hash,允许用户自定义hash的key,key可以是字符串、变量或组合。
例如,key可以是配对的源 IP 地址和端口,也可以是 URI,如以下示例所示:
|
|
请注意:基于 IP 的哈希算法存在一个问题,那就是当有一个上游服务器宕机或者扩容的时候,会引发大量的路由变更,进而引发连锁反应,导致大量缓存失效等问题。
健康检查(Health Check)
在使用负载均衡时,确保后端服务器的健康状态非常重要。Nginx 默认不支持主动的健康检查功能,但你可以通过第三方模块(如 ngx_http_upstream_check_module
)或使用 proxy_next_upstream
等指令来实现简单的被动健康检查。
在反向代理中,如果后端服务器在某个周期内响应失败次数超过规定值,nginx会将此服务器标记为失败,并在之后的一个周期不再将请求发送给这台服务器。
通过fail_timeout 来设置检查周期,默认为10秒。
通过max_fails来设置检查失败次数,默认为1次。
在以下示例中,如果NGINX无法向服务器发送请求或在30秒内请求失败次数超过3次,则会将服务器标记为不可用30秒。
|
|
在上面的示例中,proxy_next_upstream
指令配置了在发生特定错误(如超时或 HTTP 502、503、504 错误)时,Nginx 会尝试将请求转发给下一个可用的上游服务器。
HTTPS 配置
HTTPS 协议是由 HTTP 加上 TLS/SSL 协议构建的可进行加密传输、身份认证的网络协议,主要通过数字证书、加密算法、非对称密钥等技术完成互联网数据传输加密,实现互联网传输安全保护。
生成证书
|
|
配置 ssl
|
|
如果设置了密码,需要加上
|
|
https 优化
SSL 操作会消耗额外的 CPU 资源。CPU 占用最多的操作是 SSL 握手。有两种方法可以最大程度地减少每个客户端的这些操作数:
使保持活动连接能够通过一个连接发送多个请求
重用 SSL 会话参数以避免并行连接和后续连接的 SSL 握手
会话存储在工作进程之间共享并由 ssl_session_cache 指令配置的 SSL 会话缓存中。一兆字节的缓存包含大约 4000 个会话。默认缓存超时为 5 分钟。可以使用 ssl_session_timeout 指令增加此超时。以下是针对具有 10 MB 共享会话缓存的多核系统优化的示例配置:
|
|
步骤 4:测试和重启 Nginx
在完成配置后,测试 Nginx 配置的正确性:
sudo nginx -t
如果没有错误,重启 Nginx 使更改生效:
sudo systemctl restart nginx
步骤 5:验证 HTTPS 配置
最后,打开浏览器,访问你的域名,检查是否通过 HTTPS 正常加载并查看 SSL 证书是否有效。
重写(return和rewrite)
在 Nginx 中,return
和 rewrite
都是用于处理 URL 重定向和重写的重要指令,但它们有不同的用途和行为。下面是对它们的详细解释:
return
指令
return
指令用于立即停止处理并返回一个特定的 HTTP 状态码和可选的文本或 URL。它主要用于简单的重定向或响应。
使用场景:
- 重定向:当你希望将请求重定向到另一个 URL。
- 返回自定义响应:直接返回一个特定的状态码和响应体,而不继续处理请求。
语法:
|
|
示例 1:返回一个重定向
|
|
在这个例子中,所有到 example.com
的 HTTP 请求将被重定向到 https://www.example.com
,并保持请求的路径不变。
示例 2:返回自定义状态码
|
|
这将为请求 /
路径的用户返回一个 403 Forbidden
的响应,并显示 “Access forbidden”。
rewrite
指令
rewrite
指令用于基于正则表达式来重写请求的 URL。它通常用于更复杂的场景,如将旧的 URL 重写为新的结构,或根据请求条件进行 URL 改写。
使用场景:
- URL 重写:用于重写请求的 URL 而不改变浏览器地址栏中的 URL。
- 条件匹配:可以根据特定的条件或规则对请求进行处理。
语法:
|
|
regex
: 要匹配的正则表达式。replacement
: 替换后的 URL。flag
: 可选标志,影响rewrite
的行为,如last
,break
,redirect
,permanent
。
示例 1:简单的 URL 重写
|
|
这个配置会将 /old-path/something
重写为 /new-path/something
。last
标志告诉 Nginx 停止当前的重写并重新开始处理新路径。
示例 2:永久重定向
|
|
这个例子将 /old-page
重定向到 /new-page
,并返回 HTTP 301 状态码,表示这是一个永久重定向。
return
与 rewrite
的区别
return
更直接:return
直接返回一个状态码或 URL,并终止进一步的处理。适用于简单的重定向或直接响应。rewrite
更灵活和复杂:rewrite
可以对 URL 进行复杂的匹配和替换,还可以继续执行后续的处理。适用于复杂的 URL 重写逻辑。如果只是简单的重定向或需要返回特定的状态码,使用
return
会更直观。如果需要根据请求路径进行复杂的重写或条件匹配,使用
rewrite
会更适合。
在配置 Nginx 时,遵循一些推荐的写法和最佳实践可以提升配置的可维护性、安全性和性能。以下是一些关键的建议:
组织配置文件
使用 Include 指令
模块化配置:将不同功能的配置分割到多个文件中,例如将
server
块配置放在一个文件中,upstream
块配置放在另一个文件中。然后使用include
指令将这些配置包含到主配置文件中。1 2 3
# 在 /etc/nginx/nginx.conf 中 include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*;
保持配置整洁
注释:添加注释来解释配置的目的,尤其是复杂的配置。
1 2 3 4 5 6
# 将所有 HTTP 请求重定向到 HTTPS server { listen 80; server_name example.com; return 301 https://$host$request_uri; }
SSL/TLS 安全配置
强制使用 HTTPS
重定向 HTTP 到 HTTPS:确保所有 HTTP 流量自动重定向到 HTTPS,以确保传输安全。
1 2 3 4 5
server { listen 80; server_name example.com; return 301 https://$host$request_uri; }
使用现代 SSL 配置
配置 SSL/TLS:启用现代 TLS 协议,禁用过时的协议和加密套件。
1 2 3
ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH'; ssl_prefer_server_ciphers on;
启用 HTTP/2
性能优化:HTTP/2 可以显著提升 HTTPS 的性能,特别是在多资源加载的情况下。
1 2 3 4 5
server { listen 443 ssl http2; server_name example.com; # SSL 配置... }
使用 HSTS
强制安全连接:通过 HTTP Strict Transport Security (HSTS) 头,强制客户端总是使用 HTTPS。
1
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
性能优化
启用 Gzip 压缩
压缩传输数据:通过启用 Gzip 压缩,减少传输的数据量,提高页面加载速度。
1 2 3
gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; gzip_min_length 256;
使用缓存
静态文件缓存:缓存静态资源如 CSS、JS 和图片,以减少服务器负载并提高响应速度。
1 2 3 4
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control "public"; }
配置 Worker 进程
并发处理:根据服务器的 CPU 核心数调整
worker_processes
的数量。1
worker_processes auto;
安全配置
隐藏 Nginx 版本号
隐藏服务器信息:避免泄露服务器软件的版本信息,减少被特定漏洞攻击的风险。
1
server_tokens off;
限制请求体大小
防止 DDoS 攻击:限制请求体大小,防止客户端发送过大的请求占用服务器资源。
1
client_max_body_size 1m;
访问控制
基于 IP 的访问控制:使用
allow
和deny
指令限制对某些资源的访问。1 2 3 4
location /admin { allow 192.168.1.0/24; deny all; }
监控和日志
配置详细日志
访问日志和错误日志:合理配置访问日志和错误日志,帮助诊断和分析问题。
1 2
access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log warn;
日志格式定制
定制化日志:使用自定义日志格式,记录对业务更有价值的信息。
1 2 3
log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';
优雅处理错误
自定义错误页面
用户友好的错误页面:自定义错误页面,改善用户体验,避免暴露服务器信息。
1 2 3 4 5
error_page 404 /custom_404.html; location = /custom_404.html { root /usr/share/nginx/html; internal; }
测试和部署
配置测试
测试配置文件:在每次修改后,使用
nginx -t
命令来验证配置文件的正确性。1
sudo nginx -t
优雅地重启 Nginx
- 避免中断:在重新加载或重启 Nginx 时使用
systemctl reload nginx
,以确保请求不中断。