Nginx是个啥?
Nginx可以是个Web服务器(提供前端静态文件的托管),也可以是个代理服务器(请求转发)。
Web服务器:处理客户端请求并返回网页内容的软件。
我们常见的Web服务器有:IIS、Tomcat、Node.js……
Nginx能用来干嘛?
在me的认知里面,Nginx可以用来:
- 部署前端代码
- 系统网关服务,可以将客户端请求转发到后端服务器上;可以实现负载均衡,将请求分发到多个服务器上
Nginx怎么使用?
使用Nginx实现负载均衡:
http {
upstream backend {
server 192.168.1.100;
server 192.168.1.101;
}
server {
listen 80;
location / {
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;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
upstream backend
:块定义了一个名为 backend 的服务器组,其中包含两个服务器
location /
:定义了如何处理对根路径的请求。proxy_pass http://backend; 指令将请求转发到 backend 服务器组中的一个服务器。
关键字:upstream
&server location
关于Nginx 负载均衡策略配置,这里不做分析,Nginx默认的负载均衡策略是轮询。
使用Nginx实现请求转发:
server {
listen 80;
server_name example.com;
location /api {
proxy_pass http://backend-server:8080;
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;
}
}
location /api
定义了如何处理对 /api 路径的请求。proxy_pass http://backend-server:8080; 指令将请求转发到 http://backend-server:8080。这样配置后,所有对 http://example.com/api 的请求都会被Nginx转发到 http://backend-server:8080。
常见的有:
- 配置Nginx动静分离
server {
listen 80;
server_name example.com;
# 静态资源路径
root /var/www/html;
# 静态资源缓存控制
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, no-transform";
}
# 动态请求转发
location /api {
proxy_pass http://backend-server:8080;
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;
}
# 默认静态文件处理
location / {
try_files $uri $uri/ =404;
}
}
-
配置Nginx限流(可以有IP限流、URL路径限流等)
http { # 定义限流区域 limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { listen 80; server_name example.com; # 使用限流区域 location / { limit_req zone=one burst=5 nodelay; proxy_pass http://backend-server:8080; 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; } } }
-
Nginx配置SSL证书(HTTPS可以提供更安全的连接)
server { listen 80; server_name example.com www.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name example.com www.example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; ssl_prefer_server_ciphers on; root /var/www/html; index index.html index.htm; location / { try_files $uri $uri/ =404; } }
另外需要关注的Nginx的安全问题包括:
- 隐藏Nginx的版本号信息
- 限制访问敏感目录
- 自定义设置404、500等错误页面
- 尽可能启动HTTPS
- 应用内容安全策略(CSP
Content Security Policy
),比如说可以规避跨站脚本攻击(XSS)
……
这里简单了解两个名词:DDOS攻击(分布式拒接服务 Distributed Denial of Service
)+XSS攻击(Cross-Site Scripting
)
DDOS攻击
:目的是使目标服务器或网络资源无法正常提供服务。指的是同时向目标服务器发送大量请求,导致服务器资源耗尽,无法处理合法用户的请求
XSS攻击
:通过在网页中注入恶意脚本,使这些脚本在用户的浏览器中执行,从而窃取用户数据或进行其他恶意操作。
<p style="color: red">一般情况下, 上传静态资源Nginx会立即读取新文件,只有修改了nginx.conf文件,才需要执行nginx -s reload来重新加载配置文件。</p>
另外我们知道Nginx作为代理服务器既可以实现正向代理又可以实现反向代理:
正向代理:它代理的是<font color="red">客户端</font>,代客户端发出请求,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后 代理向原始服务器转交请求并将获得的内容返回给客户端。(此时服务器只知道请求来自哪个代理服务器,而不知道是哪个客户端发起的请求,正向代理模式屏蔽或者隐藏了真实客户端的信息)
server {
listen 8080;
location / {
resolver 8.8.8.8; # 使用Google的DNS服务器进行域名解析
proxy_pass http://$http_host$request_uri;
proxy_set_header Host $http_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;
}
}
所以:使用Nginx作为Web服务器的时候,基于Nginx发起的请求一般都是正向代理。
反向代理:客户端将请求发送至反向代理服务器,由反向代理服务器帮我们决定需要访问哪个资源并且将资源返回给我们,此时它代理的是<font color="red">服务端</font>。此时反向代理服务器和目标服务器对外就是服务器,但是只对外暴露了代理服务器的地址,目标服务器的地址是隐藏的。
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend-server:8080;
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;
}
}
这个体现在微服务结构中,作为API网关时,隐藏内部服务器的真实IP地址。
不管是正向代理还是反向代理,目标服务器都不知道客户端,只能看到代理服务器的IP地址,只有代理服务器才知道客户端,因为它直接与客户端通信。
我之前一个项目使用到的nginx.conf文件配置:
user nginx;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
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;
error_log /var/log/nginx/error.log;
sendfile on;
keepalive_timeout 65;
# 生产环境配置
server {
listen 8080;
server_name localhost;
# 根目录
root /var/www/html;
# 日志配置
access_log /var/log/nginx/prod.access.log;
error_log /var/log/nginx/prod.error.log;
# 处理 /mobile/ 请求
location /mobile/ {
alias /var/www/html/mobile/;
try_files $uri $uri/ =404;
}
# 处理其他请求
location / {
alias /var/www/html/pc/;
try_files $uri $uri/ =404;
}
}
# 开发环境配置
server {
listen 8081;
server_name localhost;
# 根目录
root /var/www/devHtml;
# 日志配置
access_log /var/log/nginx/dev.access.log;
error_log /var/log/nginx/dev.error.log;
# 处理 /mobile/ 请求
location /mobile/ {
alias /var/www/devHtml/mobile/;
try_files $uri $uri/ =404;
}
# 处理其他请求
location / {
alias /var/www/devHtml/pc/;
try_files $uri $uri/ =404;
}
}
}
这个指的是在nginx.conf文件中同时指定开发环境生产环境,同时打包了pc端和mobile端的静态资源,生产环境的监听的端口是8080,测试环境监听的端口是8081,pc端的静态资源通过http://ip:port/pc/请求,mobile端的静态资源通过http://ip:port/mobile请求。
另外提供一个nginx.conf文件加强理解:
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 限制body大小
client_max_body_size 100m;
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;
upstream server {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
upstream monitor-admin {
server 127.0.0.1:9090;
}
upstream xxljob-admin {
server 127.0.0.1:9100;
}
server {
listen 80;
server_name localhost;
# https配置参考 start
#listen 443 ssl;
# 证书直接存放 /docker/nginx/cert/ 目录下即可 更改证书名称即可 无需更改证书路径
#ssl on;
#ssl_certificate /etc/nginx/cert/xxx.local.crt; # /etc/nginx/cert/ 为docker映射路径 不允许更改
#ssl_certificate_key /etc/nginx/cert/xxx.local.key; # /etc/nginx/cert/ 为docker映射路径 不允许更改
#ssl_session_timeout 5m;
#ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#ssl_prefer_server_ciphers on;
# https配置参考 end
# 演示环境配置 拦截除 GET POST 之外的所有请求
# if ($request_method !~* GET|POST) {
# rewrite ^/(.*)$ /403;
# }
# location = /403 {
# default_type application/json;
# return 200 '{"msg":"演示模式,不允许操作","code":500}';
# }
# 限制外网访问内网 actuator 相关路径
location ~ ^(/[^/]*)?/actuator(/.*)?$ {
return 403;
}
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://server/;
}
# https 会拦截内链所有的 http 请求 造成功能无法使用
# 解决方案1 将 admin 服务 也配置成 https
# 解决方案2 将菜单配置为外链访问 走独立页面 http 访问
location /admin/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://monitor-admin/admin/;
}
# https 会拦截内链所有的 http 请求 造成功能无法使用
# 解决方案1 将 xxljob 服务 也配置成 https
# 解决方案2 将菜单配置为外链访问 走独立页面 http 访问
location /xxl-job-admin/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://xxljob-admin/xxl-job-admin/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
结尾
giao!!!