特点
- 支持热部署,几乎可以做到 7*24 小时不间断运行
- 支持不间断服务的情况下进行软件版本热更新
- 占用内存少
- 并发能力强、能支持高达5w并发连接
- 典型使用场景
- 静态资源服务
- 反向代理服务
- API服务(OpenResty:一个基于 NGINX 的可伸缩的 Web 平台)
- 擅长底层服务端资源处理(静态资源转发、反向代理、负载均衡等)
相关概念
-
跨域资源共享(
CORS
,Cross Origin Resource Sharing)是一种基于HTTP头的机制,新增了一组HTTP头字段。
对那些可能对服务器数据产生副作用的HTTP请求方法(特别是GET以外的HTTP请求,或者搭配某些MIME类型的POST请求),浏览器必须首先使用
OPTIONS
方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求 -
涉及到
CORS
的请求,分为简单请求和复杂请求,详细说明- 简单请求
- 复杂请求
-
同源策略:如果两个
URL
的protocol
、port
、host
都相同,则这两个URL
同源。 -
在浏览器上当前访问的网站向另一个网站发送请求获取数据的过程就是跨域请求
-
正向代理 Reverse Proxy与反向代理 Forward Proxy
-
正向代理: 一般的访问流程是客户端直接向目标服务器发送请求并获取内容,使用正向代理后,客户端改为向代理服务器发送请求,并指定目标服务器(原始服务器),然后由代理服务器和原始服务器通信,转交请求并获得内容,再返回给客户端。
正向代理隐藏了真实的客户端
,为客户端收发请求,使真实客户端对服务器不可见。 -
反向代理:与一般访问流程相比,使用反向代理后,直接收到请求的服务器是代理服务器,然后将请求转发给内部网络上真正进行处理的服务器,得到的结果返回给客户端。
反向代理隐藏了真实的服务器
,为服务器收发请求,使真实服务器对客户端不可见。一般在处理跨域请求的时候比较常用。现在基本上所有的大型网站都设置了反向代理。
-
-
负载均衡:由于服务器性能瓶颈造成的问题,除了堆机器外,最重要的做法就是负载均衡。请求爆发式增长的情况下,单个机器性能再强劲也无法满足要求了,这个时候集群的概念产生了,单个服务器解决不了的问题,可以使用多个服务器,然后将请求分发到各个服务器上,将负载分发到不同的服务器,这就是负载均衡。
Nginx
实现负载均衡,一般来说指的是将请求转发给服务器集群 -
动静分离:将动态页面与静态页面由不同的服务器解析,加快解析速度,降低单服务器压力
一般来说,都需要将动态资源和静态资源分开,由于 Nginx 的高并发和静态资源缓存等特性,经常将静态资源部署在 Nginx 上。如果请求的是静态资源,直接到静态资源目录获取资源,如果是动态资源的请求,则利用反向代理的原理,把请求转发给对应后台应用去处理,从而实现动静分离。
使用前后端分离后,可以很大程度提升静态资源的访问速度,即使动态服务不可用,静态资源的访问也不会受到影响。
安装
- Windows:Windows参考地址
- CentOS7:CentOS7参考地址
常用操作指令
# 向主进程发送信号,重新加载配置文件,热重启
nginx -s reload
# 重启 Nginx
nginx -s reopen
# 快速关闭
nginx -s stop
# 等待工作进程处理完成后关闭
nginx -s quit
# 查看当前 Nginx 最终的配置
nginx -T
# 检查配置是否有问题,如果已经在配置目录,则不需要-c
nginx -t -c <配置路径>
# Linux系统上的管理工具systemctl
# 启动 Nginx
systemctl start nginx
# 停止 Nginx
systemctl stop nginx
# 重启 Nginx
systemctl restart nginx
# 重新加载 Nginx,用于修改配置后
systemctl reload nginx
# 设置开机启动 Nginx
systemctl enable nginx
# 关闭开机启动 Nginx
systemctl disable nginx
# 查看 Nginx 运行状态
systemctl status nginx
Nginx配置语法
-
nginx.conf 结构图概括
main # 全局配置,对全局生效 ├── events # 配置影响 Nginx 服务器或与用户的网络连接 ├── http # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置 │ ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分 │ ├── server # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块 │ ├── server │ │ ├── location # server 块可以包含多个 location 块,location 指令用于匹配 uri │ │ ├── location │ │ └── ... │ └── ... └── ...
-
语法规则
- 配置文件由指令与指令块构成;
- 每条指令以
;
分号结尾,指令与参数间以空格符号分隔; - 指令块以
{}
大括号将多条指令组织在一起; include
语句允许组合多个配置文件以提升可维护性;- 使用
#
符号添加注释,提高可读性; - 使用
$
符号使用变量; - 部分指令的参数支持正则表达式;
详细配置参考:Nginx.conf配置详解
-
全局变量
搜索技巧:nginx 内置预定义变量
配置反向代理
server {
listen 9001;
server_name *.myserver.com;
# http://127.0.0.1:9001/edu 的请求转发到 http://127.0.0.1:8080
location ~ /edu/ {
proxy_pass http://127.0.0.1:8080;
}
# http://127.0.0.1:9001/vod 的请求转发到 http://127.0.0.1:8081
location ~ /vod/ {
proxy_pass http://127.0.0.1:8081;
}
}
proxy_set_header
:在将客户端请求发送给后端服务器之前,更改来自客户端的请求头信息;proxy_connect_timeout
:配置 Nginx 与后端代理服务器尝试建立连接的超时时间;proxy_read_timeout
:配置 Nginx 向后端服务器组发出 read 请求后,等待相应的超时时间;proxy_send_timeout
:配置 Nginx 向后端服务器组发出 write 请求后,等待相应的超时时间;proxy_redirect
:用于修改后端服务器返回的响应头中的 Location 和 Refreshproxy_pass
:将当前请求反向代理到URL参数指定的服务器上,URL可以是主机名或者IP地址加端口的形式
跨域CORS
配置
# 一个大门全开的跨域配置例子
location ~ \.do$ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE' always;
add_header 'Access-Control-Allow-Headers' '*' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
if ($request_method ~* '(GET|POST|DELETE|PUT)') {
add_header 'Access-Control-Allow-Origin' '*' always;
}
}
-
使用反向代理解决跨域
# 前端服务:fe.sherlocked93.club ,后端服务:be.sherlocked93.club # 1、将fe.*的请求全部代理到be.*上。统一了请求地址,不易区分 server { listen 9001; server_name fe.sherlocked93.club; location / { proxy_pass be.sherlocked93.club; } } # 2、约定代理后端服务请求path以/apis/开头 location ^~/apis/ { # 这里重写了请求,将正则匹配中的第一个分组的path拼接到真正的请求后面,并用break停止后续匹配 rewrite ^/apis/(.*)$ /$1 break; proxy_pass be.sherlocked93.club; # 两个域名之间cookie的传递与回写 proxy_cookie_domain be.sherlocked93.club fe.sherlocked93.club; } # 3、把前后端服务器地址直接都转发到另一个 server.sherlocked93.club,只通过在后面添加的 path 来区分请求的是静态资源还是后端服务
-
配置header解决跨域
server { listen 80; server_name be.sherlocked93.club; # 全局变量获得当前请求origin,带cookie的请求不支持* add_header 'Access-Control-Allow-Origin' $http_origin; # 为 true 可带上 cookie add_header 'Access-Control-Allow-Credentials' 'true'; # 允许请求方法 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; # 允许请求的 header,可以为 * add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers; add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range'; if ($request_method = 'OPTIONS') { # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求 add_header 'Access-Control-Max-Age' 1728000; add_header 'Content-Type' 'text/plain; charset=utf-8'; add_header 'Content-Length' 0; # 200 也可以 return 204; } location / { root /usr/share/nginx/html/be; index index.html; } }
开启gzip
压缩
-
gzip 是一种常用的网页压缩技术,传输的网页经过 gzip 压缩之后大小通常可以变为原来的一半甚至更小
-
使用 gzip 不仅需要
Nginx
配置,浏览器
端也需要配合,需要在请求消息头中包含Accept-Encoding: gzip
-
一般在请求html或css等静态资源时,支持的浏览器在
request
请求静态资源时,会加上Accept-Encoding: gzip
(一般是说明支持的多种压缩方式)标明自己支持的压缩方式;Nginx 在拿到这个请求后返回经过 gzip 压缩过的文件给浏览器,并在 response 相应的时候加上content-encoding: gzip
来告诉浏览器自己采用的压缩方式 -
一般 gzip 的配置建议加上
gzip_min_length 1k
(小于1kb的文件不使用压缩 – 压缩后体积更大了😂)
# 默认off,是否开启gzip
gzip on;
# 要采用 gzip 压缩的 MIME 文件类型,其中 text/html 被系统强制启用
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# 上面两个开启基本就能跑起了,下面的愿意折腾就了解一下
# 默认 off,启用后,首先检查是否存在请求静态文件的 gz 结尾的文件,如果有则直接返回该 .gz 文件内容
gzip_static on;
# 默认 off,做为反向代理时启用,用于设置启用或禁用从代理服务器上收到相应内容 gzip 压缩
gzip_proxied any;
# 用于在响应消息头中添加 Vary:Accept-Encoding,使代理服务器根据请求头中的 Accept-Encoding 识别是否启用 gzip 压缩
gzip_vary on;
# gzip 压缩比,压缩级别是 1-9,1 压缩级别最低,9 最高,级别越高压缩率越大,压缩时间越长,建议 4-6
gzip_comp_level 6;
# 获取多少内存用于缓存压缩结果,16 8k 表示以 8k*16 为单位获得
gzip_buffers 16 8k;
# 允许压缩的页面最小字节数,页面字节数从 header 头中的 Content-Length 中进行获取。默认值是 0,不管页面多大都压缩。建议设置成大于 1k 的字节数,小于 1k 可能会越压越大
# gzip_min_length 1k;
# 默认 1.1,启用 gzip 所需的 HTTP 最低版本
gzip_http_version 1.1;
Webpack
的gzip
配置需要在前端出包时实现;如果全都是使用Nginx
来压缩文件,会耗费服务器的计算资源,如果服务器的gzip_comp_level
配置的比较高,就更增加服务器的开销;将压缩之后的文件作为静态文件存放在服务器上,Nginx
会优先查找压缩之后的文件返回给客户端,相当于提前打包完成- 一般推荐生产环境应用
Webpack
配置gzip
压缩 - 可以配置在
http
模块的整个服务器的配置里,也可以配置在需要使用的虚拟主机的server
或下面的location
模块中
配置负载均衡
# 负载均衡配置
http {
upstream myserver {
# ip_hash 方式
# ip_hash;
# fair 方式
# fair;
# 负载均衡目的服务地址
server 127.0.0.1:8081;
server 127.0.0.1:8080;
# weight 权重配置,不写默认为 1
server 127.0.0.1:8082 weight=10;
}
server {
location / {
proxy_pass http://myserver;
proxy_connect_timeout 10;
}
}
}
Nginx
提供了几种分配方式,默认为轮询。有以下几种方式:
- 轮询:默认每个请求按照时间顺序逐一分配到不同的后端服务器,如果服务挂了则自动剔除
- weight:权重分配;指定轮询几率,权重越高,被访问的概率越大,用于后端服务器性能不均的情况
- ip_hash:每个请求按访问
IP
的hash
结果分配,这样每个IP
固定访问一个后端服务器,可以解决动态网页session
共享问题。负载均衡每次请求都会重新定位到服务器集群中的某一个,那么已经登录某一个服务器的用户再重新定位到另一个服务器,其登录信息将会丢失,这样显然是不妥的 fair
:第三方提供;按照后端服务器的响应时间分配,响应时间短的优先分配,依赖第三方插件nginx-upstream-fair
动静分离配置
-
实现将动态与静态的请求分离,有两种方式:
- 把静态文件独立成单独的域名,放在独立的服务器上。目前主流推崇的方案
- 将动态与静态文件一起发布,通过
Nginx
配置进行分离
-
通过
location
指定不同的后缀实现不同的请求转发。通过设置expire
参数,使浏览器缓存过期时间,减少与服务器之间的请求与流量expire
:给一个资源设定一个过期时间,无需去服务端验证,直接通过浏览器自身确认是否过期即可。适用于不经常变动的资源
# 动静分离
server {
listen 80;
server_name kevin.com;
access_log /data/nginx/logs/kevin.com-access.log main;
error_log /data/nginx/logs/kevin.com-error.log;
upstream myserver {
server 127.0.0.1:8081;
server 127.0.0.1:8080;
}
# 动态资源
location ~ .(jsp|do)?$ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://myserver;
}
# 静态资源
location ~ .*.(html|htm|js|css|jpg|png)$ {
# 3天之内访问资源,对比文件最后更新时间;没有变化则不会抓取,返回状态码304;修改则抓取并返回200
expires 3d;
root /data/web/html;
}
}
配置高可用集群(双机热备)
依赖于组件keepalived
适配PC或移动设备
根据用户请求的user-agent
判断返回PC
或H5
站点
server {
listen 80;
server_name fe.sherlocked93.club;
location / {
root /usr/share/nginx/html/pc;
# 如果为移动端访问,修改根目录为移动端网页所在目录
if ($http_user_agent ~* '(Android|webOS|iPhone|iPod|BlackBerry)') {
root /usr/share/nginx/html/mobile;
}
index index.html;
}
}
配置HTTPS
server {
# SSL 访问端口号为 443
listen 443 ssl http2 default_server;
# 填写绑定证书的域名
server_name sherlocked93.club;
# 这几项安全增强命令
# 减少点击劫持
add_header X-Frame-Options DENY;
# 禁止服务器自动解析资源类型
add_header X-Content-Type-Options nosniff;
# 防XSS攻击
add_header X-Xss-Protection 1;
# 证书文件地址(证书需要申请)
ssl_certificate /etc/nginx/https/1_sherlocked93.club_bundle.crt;
# 私钥文件地址
ssl_certificate_key /etc/nginx/https/2_sherlocked93.club.key;
ssl_session_timeout 10m;
# 请按照以下协议配置
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
参考地址:Nginx 从入门到实践,万字详解!