基于前端程序员的Nginx 入门科普

219 阅读5分钟

Nginx 能做什么

如今基本上所有的大型网站都搭建在Nginx之上,Nginx不再是一个什么新词,而是互联网网站搭建的必选技术之一。

"HTTP服务器”、“事件驱动”、“异步非阻塞”,是不是让WEB开发者们想到了 Nodejs?

确实Nginx中的绝大部分功能,如果单纯的使用Nodejs也可以满足和实现。但实际上,Nginx和Nodejs并不冲突,都有自己擅长的领域:

Nginx更擅长于底层服务器端资源的处理(静态资源处理转发、反向代理,负载均衡等)

Node.js更擅长于上层具体业务逻辑的处理。

两者可以实现完美组合,助力WEB开发

例如:

快速实现简单的访问限制 我们经常会遇到希望网站让某些特定用户的群体(只让公司内网)访问,或者控制某个URI不让人访问。

解决跨域 在众多的解决跨域方式中,都需要服务端进行支持,使用Nginx可以解决请求跨域问题。

适配PC与移动环境 现在很多网站都存在PC站和H5站两个站点,因此根据用户的浏览环境自动切换站点是很常见的需求。Nginx可以通过内置变量获取到请求客户端的UerAgent,从而知道用户处于移动端还是PC,进而控制重定向到H5站还是PC站。而且Nginx一般处于边缘节点,离用户最近

合并请求 WEB开发性能优化中,最重要的就是尽量减少HTTP资源请求的数量。通过Nginx-Http-Concat模块(淘宝开发的第三方模块,需要单独安装)用一种特殊的请求URL规则,WEB开发可以将多个资源的请求合并成一个请求,后台Nginx会获取各个资源并拼接成一个结果进行返回。

HTTP服务器(动静分离) / 缓存 / 权限控制 / 反向代理 / 负载均衡 / 灰度测试 / 容灾处理 / 防盗链

后面会一一介绍

什么是Nginx

Nginx是一款轻量级的HTTP服务器,采用事件驱动的异步非阻塞处理方式框架,这让其具有极好的IO性能,时常用于服务端的反向代理和负载均衡。

Nginx 优点

  • 支持海量高并发,并且稳定
  • 内存消耗少
  • 可商业化
  • 配置文件简单

Nginx 的源码安装完整步骤

需要注意的是 在 CentOS 8 以上版本yum需要换源

  • yum -y install gcc openssl openssl-devel pcre-devel zlib zlib-devel
  • wget http://nginx.org/download/nginx-1.16.1.tar.gz
  • mkdir -p nginx/core
  • mv nginx-1.16.1.tar.gz nginx/core
  • cd nginx/core
  • tar -xzf nginx-1.16.1.tar.gz
  • cd ./nginx-1.16.1
  • ./configure --prefix=/usr/local/nginx \
    --sbin-path=/usr/local/nginx/sbin/nginx \
    --modules-path=/usr/local/nginx/modules \
    --conf-path=/usr/local/nginx/conf/nginx.conf \
    --error-log-path=/usr/local/nginx/logs/error.log \
    --http-log-path=/usr/local/nginx/logs/access.log \
    --pid-path=/usr/local/nginx/logs/nginx.pid \
    --lock-path=/usr/local/nginx/logs/nginx.lock
    
  • make && make install
  • cd /usr/local/nginx/sbin
  • ./nginx

image.png

然后访问公网IP即可,出现该页面代表已经安装成功

此时的安装路径在:/usr/local/nginx

如果不知道安装到哪里可以使用find -name nginx 即可

nginx文件介绍

nginx我们最常用到的文件,其实就是nginx的配置文件

在nginx.conf 文件当中 # 是注释

├── client_body_temp
├── conf                             # Nginx所有配置文件的目录
│   ├── fastcgi.conf                 # fastcgi相关参数的配置文件
│   ├── fastcgi.conf.default         # fastcgi.conf的原始备份文件
│   ├── fastcgi_params               # fastcgi的参数文件
│   ├── fastcgi_params.default       
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types                   # 媒体类型
│   ├── mime.types.default
│   ├── nginx.conf                   # Nginx主配置文件
│   ├── nginx.conf.default
│   ├── scgi_params                  # scgi相关参数文件
│   ├── scgi_params.default  
│   ├── uwsgi_params                 # uwsgi相关参数文件
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp                     # fastcgi临时数据目录
├── html                             # Nginx默认站点目录
│   ├── 50x.html                     # 错误页面优雅替代显示文件,例如当出现502错误时会调用此页面
│   └── index.html                   # 默认的首页文件
├── logs                             # Nginx日志目录
│   ├── access.log                   # 访问日志文件
│   ├── error.log                    # 错误日志文件
│   └── nginx.pid                    # pid文件,Nginx进程启动后,会把所有进程的ID号写到此文件
├── proxy_temp                       # 临时目录
├── sbin                             # Nginx命令目录
│   └── nginx                        # Nginx的启动命令
├── scgi_temp                        # 临时目录
└── uwsgi_temp                       # 临时目录

查看日志

  • tail -f ./nginx/logs/access.log
  • tail -f ./nginx/logs/error.log

image.png

此时在控制台终端可以实时打印出访问的日志信息

使用 nginx 命令

使用nginx 命令有三种方式,本文只介绍两种

第一种:在nginx 的安装目录下找到 sbin 目录下的 nginx 文件即可

第二种:将nginx 配置成全局变量环境

vim /etc/profile
​
// 在最后一行加上
PATH=$PATH:/usr/local/nginx/sbin
export PATH
​
source /etc/profile
​
// 最后检验是否配置成功
nginx -v
// nginx version: nginx/x.xx.x 

常见 nginx 命令

启动nginx :nginx

查看nginx版本:nginx -v

测试nginx配置文件:nginx -t 出现 test is successful 表示测试成功

热启动nginx:nginx :nginx -s reload

一般流程为,当修改了配置文件 执行 nginx -t 然后nginx -s reload 即可

Nginx 配置文件模块介绍

worker_processes  1;
​
events {
    worker_connections  1024;
}
​
http {
    include       mime.types;
    default_type  application/octet-stream;
​
    sendfile        on;
​
    keepalive_timeout  65;
​
    server {
        listen       80;
        server_name  localhost;
​
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}
​

nginx.conf配置文件中默认有三大块

全局模块:设置Nginx服务器整体运行的配置指令

events模块:设置Nginx服务器与用户的网络连接,这一部分对 Nginx服务器的性能影响较大

http模块:Nginx服务器配置中的重要部分,代理、缓存、日志记录、 第三方模块配置...

注意

http模块中可以配置多个server模块,每个server模块又可以配置多个location模块

server模块:Nginx配置和虚拟主机相关的内容

location模块:基于Nginx服务器接收请求字符串与 location后面的值进行匹配,对特定请求进行处理

Nginx 全局模块常用命令介绍

user: 用户名

作用:需要location root 中的资源文件要在当前配置的服务器登陆用户的权限目录文件夹当中,否则访问报403 无权限访问

work process:用于配置Nginx生成工作进程的数量

作用:这个是Nginx服务器实现并发处理服务的关键所在。理论上来说workder process的值越大,可以支持的并发处理量也越多,但事实上这个值的设定是需要受到来自服务器自身的限制,建议将该值和服务器CPU的内核数保存一致。

include: 用来引入其他配置文件,使Nginx的配置更加灵活

Nginx events模块常用命令介绍

accept_mutex: 用来设置Nginx网络连接序列化

默认值:on

作用:这个配置主要可以用来解决常说的"惊群"问题。大致意思是在某一个时刻,客户端发来一个请求连接,Nginx后台是以多进程的工作模式,也就是说有多个worker进程会被同时唤醒,但是最终只会有一个进程可以获取到连接,如果每次唤醒的进程数目太多,就会影响Nginx的整体性能。如果将上述值设置为on(开启状态),将会对多个Nginx进程接收连接进行序列号,一个个来唤醒接收,就防止了多个进程对连接的争抢。

multi_accept: 用来设置是否允许同时接收多个网络连接

默认值:off

作用:如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接

worker_connections:用来配置单个worker进程最大的连接数

默认值:512

作用:这里的连接数不仅仅包括和前端用户建立的连接数,而是包括所有可能的连接数。另外,number值不能大于操作系统支持打开的最大文件句柄数量。

Nginx http模块常用命令介绍

定义MIME-Type

我们都知道浏览器中可以显示的内容有HTML、XML、GIF等种类繁多的文件、媒体等资源,浏览器为了区分这些资源,就需要使用MIME-Type。所以说MIME Type是网络资源的媒体类型。Nginx作为web服务器,也需要能够识别前端请求的资源类型。在Nginx的配置文件中,默认有两行配置

http {
    include       mime.types;
    default_type  application/octet-stream;
}

举例说明

http {
  include mime.types;
  default_type application/octet-stream;
  
  server {
    location /get_text { 
      #这里也可以设置成text/plain 
      default_type text/html;
      return 200 "This is nginx's text"; 
    }
    location /get_json{ 
      default_type application/json;
      return 200 '{"name":"TOM","age":18}'; 
    } 
  }
}

自定义服务日志

建议前端不要去修改,了解即可

Nginx中日志的类型分access.log、error.log。

access.log: 用来记录用户所有的访问请求。

error.log: 记录nginx本身运行时的错误信息,不会记录用户的访问请求。

传输文件

sendfile: 用来设置Nginx服务器是否使用sendfile()传输文件

默认值:on

该属性可以大大提高Nginx处理静态资源的性能

keepalive_timeout:用来设置长连接的超时时间

默认值:75(秒)

我们都知道HTTP是一种无状态协议,客户端向服务端发送一个TCP请求, 服务端响应完毕后断开连接。 如何客户端向服务端发送多个请求,每个请求都需要重新创建一次连接, 效率相对来说比较多,使用keepalive模式,可以告诉服务器端在处理完 一个请求后保持这个TCP连接的打开状态,若接收到来自这个客户端的其他请求,服务端就会利用这个未被关闭的连接,而不需要重新创建一个新连接,提升效率,但是这个连接也不能一直保持,这样的话,连接如果过多,也会是服务端的性能下降,这个时候就需要我们进行设置其的超时时间。

keepalive_requests:用来设置一个keep-alive连接使用的次数

默认值:100

server 和 location 模块常用命令介绍

listen用来配置监听端口

默认值:80 | 8080

listen的设置比较灵活,我们通过几个例子来把常用的设置方式熟悉下

http {
  server {
    # listen localhost:8000 监听指定的IP和端口 
    listen 127.0.0.1:8000; 
    # 监听指定IP的所有端口
    listen 127.0.0.1;  
    # 监听指定端口上的连接
    listen 8000;  
    # 监听指定端口上的连接
    listen *:8000; 
  }
}

default_server: 属性标识符

作用:用来将此虚拟主机设置成默认主机。所谓的默认主机指的是如果没有匹配到对应的server_name:port,则会默认执行的。如果不指定默认使用的是第一个server

http {
    server{ 
    listen 8080; 
    server_name 127.0.0.1; 
    location /{ 
      root html;
      index index.html; 
    }
  }
  server { 
    listen 8080 default_server; 
    server_name localhost; 
    default_type text/plain;
    return 444 'This is a error request';
  }
}

server_name:用来设置虚拟主机服务名称。

可选值:127.0.0.1 、 localhost 、域名

当然,这里面还可以通过正则来匹配,本文不会讲述

location:用来设置请求的URI

uri变量是待匹配的请求字符串,可以不包含正则表达式,也可以包含正则表达式,那么nginx服务器在搜索匹配location的时候,是先使用不包含正则表达式进行匹配,找到一个匹配度最高的一个,然后在通过包含正则表达式的进行匹配,如果能匹配到直接访问,匹配不到,就使用刚才匹配度最高的那个location来处理请求。

server { 
  listen 80; 
  server_name 127.0.0.1; 
  location /abc { 
  } 
}

上面案例当中,只要请求地址中包含 http://192.168.200.133/abc 这个即可

例如 http://192.168.200.133/abcdefg 依然可以匹配成功

在这里 /abc 前面 可以加一个符号

= : 用于不包含正则表达式的uri前,必须与指定的模式精确匹配

当然,还有别的,本文不会讲述

设置请求资源的目录root / alias

root:设置请求的根目录

默认值:html

作用:path为Nginx服务器接收到请求以后查找资源的根目录路径。

alias:用来更改location的URI

举例说明两者区别

location /images { 
  root /usr/local/nginx/html; 
}

那么访问路径就是 http://127.0.0.1/images/mv.png

location /images { 
  alias /usr/local/nginx/html; 
}

如果你这样访问 http://127.0.0.1/images/mv.png404

root的处理结果是: root路径 + location路径

结果:/usr/local/nginx/html/images/mv.png

alias的处理结果是: 使用alias路径替换location路径

结果:/usr/local/nginx/html

所以需要在alias后面路径改为

location /images { 
  alias /usr/local/nginx/html/images; 
}

index:设置网站的默认首页

默认值:index index.html

作用:index后面可以跟多个设置,如果访问的时候没有指定具体访问的资源,则会依次进行查找,找到第一个为止。

location / { 
  root /usr/local/nginx/html;
  index index.html index.htm; 
}

Nginx对静态资源如何进行优化配置

http {
  # 提高 I/O 效率
  sendfile on; 
  # 该指令必须在sendfile打开的状态下才会生效,主要是用来提升网络包的传输'效率'
  tcp_nopush on; 
  # 该指令必须在keep-alive连接开启的情况下才生效,来提高网络包传输的'实时性'
  tcp_nodeplay on;
}

image.png

"tcp_nopush"和”tcp_nodelay“看起来是"互斥的",那么为什么要将这两个值都打开,这个大家需要知道的是在linux2.5.9以后的版本中两者是可以兼容的,三个指令都开启的好处是,sendfifile可以开启高效的文件传输模式,tcp_nopush开启可以确保在发送到客户端之前数据包已经充分“填满”, 这大大减少了网络开销,并加快了文件发送的速度。 然后,当它到达最后一个可能因为没有“填满”而暂停的数据包时,Nginx会忽略tcp_nopush参数, 然后,tcp_nodelay强制套接字发送数据。由此可知,TCP_NOPUSH可以与TCP_NODELAY一起设置,它比单独配置TCP_NODELAY具有更强的性能。所以我们可以使用如下配置来优化Nginx静态资源的处理

Rewrite功能配置

地址重写和地址转发的区别

  • 地址重写浏览器地址会发生变化而地址转发则不变
  • 一次地址重写会产生两次请求而一次地址转发只会产生一次请求
  • 地址重写到的页面必须是一个完整的路径而地址转发则不需要
  • 地址重写因为是两次请求所以request范围内属性不能传递给新页面而地址转发因为是一次请求所以可以传递值

由于咱们是前端,对这块不用知道很多,这里只举一个简单的例子

例如:在对官网进行更换域名,这时候SEO检索是需要一定时间的,而且对于关键词和描述相同的是不会重新收录的,为了避免影响新网站的SEO,这时候我们需要对老域名进行重定向到新域名上面去,后续再将老域名停掉

server {
  server_name 老域名;
  # permanent 永久重定向
  rewrite ^(.*) 新域名 permanent;
}

Nginx反向代理

proxy_pass URL;

该指令用来设置被代理服务器地址,可以是主机名称、IP地址加端口号形式。

URL:为要设置的被代理服务器地址,包含传输协议( http , https:// )、主机名称或IP地址加端口号、URI等要素。

proxy_set_header

重新定义或者添加发往后端服务器的请求头

proxy_redirect

该指令是用来重置头信息中的"Location"和"Refresh"的值。

其他配置可以忽略

http {
    proxy_redirect off;
    proxy_http_version 1.1;
    # 启用支持websocket连接
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    # 浏览器请求的ip,不显示端口
    proxy_set_header Host $host;
    # 拿到的将是反向代理服务器的ip地址
    proxy_set_header X-Real-IP $remote_addr;
    # 拿到的将是用户的ip地址
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

为什么要使用反向代理 或者 正向代理

外网不可直接访问 web server 会更加安全

有些时候我们有多个服务器A | B,它们都在阿里云同一个内网中,我们需要只把A服务对外开放,但是有业务在B中,并不对外访问,只让A用制定端口从内网访问,所以需要做个配置,支持A从内网访问B服务。需要注意的是,在服务器所在的服务商控制台确认你的端口没有对外开放。

反向代理系统调优

反向代理值BufferCache

Buffer翻译过来是"缓冲",Cache翻译过来是"缓存"。

总结下:

相同点: 两种方式都是用来提供IO吞吐效率,都是用来提升Nginx代理的性能。

不同点: 缓冲主要用来解决不同设备之间数据传递速度不一致导致的性能低的问题,缓冲中的数据一旦此次操作完成后,就可以除。 缓存主要是备份,将被代理服务器的数据缓存一份到代理服务器,这样的 话,客户端再次获取相同数据的时候,就只需要从代理服务器上获取,效率较高,缓存中的数据可以重复使用,只有满足特定条件才会删除

通用配置

http {
  proxy_buffering on; 
  proxy_buffer_size 4 32k; 
  proxy_busy_buffers_size 64k; 
  proxy_temp_file_write_size 64k;
}

Nginx负载均衡

系统的扩展可以分为纵向扩展横向扩展

纵向扩展:是从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力

横向扩展:是通过添加机器来满足大型网站服务的处理能力。

image.png

这里面涉及到两个重要的角色分别是"应用集群"和"负载均衡器"。

应用集群:将同一应用部署到多台机器上,组成处理集群,接收负载均衡设备分发的请求,进行处理并返回响应的数据。

负载均衡器:将用户访问的请求根据对应的负载均衡算法,分发到集群中的一台服务器进行处理。

补充:还有一种叫分布式,就是将一个完整业务功能拆分多块业务独立提供服务,缺点就是容错率低,当一台机器有问题就会导致生产环境出现问题

负载均衡的作用

1、解决单个服务器的高并发压力,提高应用程序的处理性能。

2、提供故障转移,实现高可用。

3、通过添加或减少服务器数量,增强网站的可扩展性。

4、在负载均衡器上进行过滤,可以提高系统的安全性。

负载均衡常用的处理方式

第一种:用户自主选择服务器,例如王者荣耀选择区

第二种:DNS 轮询

简单说一下 DNS

域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于 域名IP 地址 的相互转换。

image.png

大多域名注册商都支持对同一个主机名添加多条A记录,这就是DNS轮询,DNS服务器将解析请求按照A记录的顺序,随机分配到不同的IP上,这样就能完成简单的负载均衡。DNS轮询的成本非常低,在一些不重要的服务器,被经常使用。

但DNS也是有缺点的

1.可靠性低

假设一个域名DNS轮询多台服务器,如果其中的一台服务器发生故障,那么所有的访问该服务器的请求将不会有所回应,即使你将该服务器的IP从DNS中去掉,但是由于各大宽带接入商将众多的DNS存放在缓存中,以节省访问时间,导致DNS不会实时更新。所以DNS轮流上一定程度上解决了负载均衡问题,但是却存在可靠性不高的缺点。

2.负载均衡不均衡

DNS负载均衡采用的是简单的轮询负载算法,不能区分服务器的差异,不能反映服务器的当前运行状态,不能做到为性能好的服务器多分配请求,另外本地计算机也会缓存已经解析的域名到IP地址的映射,这也会导致使用该DNS服务器的用户在一定时间内访问的是同一台Web服务器,从而引发Web服务器减的负载不均衡。负载不均衡则会导致某几台服务器负荷很低,而另外几台服务器负荷确很高,处理请求的速度慢,配置高的服务分配到的请求少,而配置低的服务器分配到的请求多。

Nginx的七层负载均衡

image.png

轮询策略(这里只介绍几种)

轮询:是upstream模块负载均衡默认的策略。每个请求会按时间顺序逐个分配到不同的后端服务器。轮询不需要额外的配置。

upstream backend{ 
  server 192.168.200.146:9001 weight=1; 
  server 192.168.200.146:9002; 
  server 192.168.200.146:9003; 
}
server { 
  listen 8083; 
  server_name localhost;
  location / { 
    proxy_pass http://backend;
  } 
}

weight[加权轮询] :用来设置服务器的权重,默认为1,权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所有此策略比较适合服务器的硬件配置差别比较大的情况。

upstream backend{ 
  server 192.168.200.146:9001 weight=10;
  server 192.168.200.146:9002 weight=5;
  server 192.168.200.146:9003 weight=3;
}
server { 
  listen 8083; 
  server_name localhost;
  location / { 
    proxy_pass http://backend;
  } 
}

ip_hash:当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个IP的用户在后端Web服务器A上登录后,在访问该站点的其他URL,能保证其访问的还是后端web服务器A。

upstream backend{ 
  ip_hash;
  server 192.168.200.146:9001;
  server 192.168.200.146:9002;
  server 192.168.200.146:9003;
}
server { 
  listen 8083; 
  server_name localhost;
  location / { 
    proxy_pass http://backend;
  } 
}

least_conn:最少连接,把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是,有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

upstream backend{ 
  least_conn;
  server 192.168.200.146:9001;
  server 192.168.200.146:9002;
  server 192.168.200.146:9003;
}
server { 
  listen 8083; 
  server_name localhost;
  location / { 
    proxy_pass http://backend;
  } 
}

url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请会到达同一台服务器,一旦缓存住了资源,再此收到请求,就可以从缓存中读取。

upstream backend{ 
  hash &request_uri;
  server 192.168.200.146:9001;
  server 192.168.200.146:9002;
  server 192.168.200.146:9003;
}
server { 
  listen 8083; 
  server_name localhost;
  location / { 
    proxy_pass http://backend;
  } 
}

Nginx 全局变量

变量含义
$args这个变量等于请求行中的参数,同$query_string
$content length请求头中的Content-length字段。
$content_type请求头中的Content-Type字段。
$document_root当前请求在root指令中指定的值。
$host请求主机头字段,否则为服务器名称。
$http_user_agent客户端agent信息
$http_cookie客户端cookie信息
$limit_rate这个变量可以限制连接速率。
$request_method客户端请求的动作,通常为GET或POST。
$remote_addr客户端的IP地址。
$remote_port客户端的端口。
$remote_user已经经过Auth Basic Module验证的用户名。
$request_filename当前请求的文件路径,由root或alias指令与URI请求生成。
$schemeHTTP方法(如http,https)。
$server_protocol请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr服务器地址,在完成一次系统调用后可以确定这个值。
$server_name服务器名称。
$server_port请求到达服务器的端口号。
$request_uri包含请求参数的原始URI,不包含主机名,如”/foo/bar.php?arg=baz”。
$uri不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri与$uri相同。

让我们回到上面的留的坑

部署单页面

如果是 history 路由

location / {
  root   目录;
  index  index.html index.htm;
  try_files $uri $uri/ /index.html
}

GZIP 压缩

Gzip是网页的一种网页压缩技术,经过gzip压缩后,页面大小可以变为原来的30%甚至更小。更小的网页会让用户浏览的体验更好,速度更快。gzip网页压缩的实现需要浏览器和服务器的支持 gzip是需要服务器和浏览器同时支持的。当浏览器支持gzip压缩时,会在请求消息中包含Accept-Encoding:gzip,这样Nginx就会向浏览器发送听过gzip后的内容,同时在相应信息头中加入Content-Encoding:gzip,声明这是gzip后的内容,告知浏览器要先解压后才能解析输出。 如果项目是在ie或者一些兼容性比较低浏览器上运行的,需要去查阅确定是否浏览器支持gzip

按照这个全局配置即可

 http {
    # 开启gzip压缩功能
    gzip  on;
    # gzip压缩最小文件大小,超出进行压缩
    gzip_min_length  50k;
    #压缩级别【1-9】,越大压缩率越高,同时消耗cpu资源也越多,建议设置在4左右。
    gzip_comp_level 6;
    # 压缩缓冲区大小。表示申请4个单位为16K的内存作为压缩结果流缓存,
    # 默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果。
    gzip_buffers  4 16k;
    # 需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片
    gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;
    # 配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
    gzip_disable "MSIE [1-6].";
    # 跟Squid等缓存服务有关,on的话会在Header里增加 "Vary: Accept-Encoding"
    gzip_vary off;
 }

Nginx静态资源缓存

Web缓存是指一个Web资源(如html页面,图片,js,数据等)存在于 Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存 输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制(强缓存,协商缓存)决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这 个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再 次下载网页

缓存种类
  • 浏览器缓存
  • 服务器缓存(Nginx / redis)

这块本文不讲述

静态资源防盗链

例如在微信公众号复制一张图片地址在浏览器打开,是打不开的,这就是防盗链

我们得先学习一个HTTP的头信息Referer,当浏览器向web服务器发送请求的时候,一般都会带上Referer,来告诉浏览器该网页是从哪个页面链接过来的。

location /images { 
  # 域名 / IP / *通配符 / 正则表达式,需要以~开头表示
  valid_referers none blocked www.baidu.com 192.168.1.1 *.example.com ~.google.; 
  if ($invalid_referer){ 
    # rewrite ^/ /images/forbidden.png break;
    return 403; 
  }
  root /usr/local/nginx/html; 
}

指定IP访问 / 限定IP访问

例如:只允许内网访问(只能在本地服务器生效)

location / { 
  # block one workstation 
  deny    192.168.1.1; 
  # allow anyone in 192.168.1.0/24 
  allow   192.168.1.0/24; 
  # drop rest of the world 
  deny    all; 
}

例如:云服务器允许部分IP访问(也就是使用VPN)

location / { 
  # block one workstation 
  deny    192.168.1.1; 
  # allow anyone in 192.168.1.0/24 
  allow   VPN 地址; 
  # drop rest of the world 
  deny    all; 
}

注意事项:

deny :禁止的ip

allow:允许的ip

deny all; 初次之外的ip全部不能访问

例如:连接频率限制

http {
  limit_conn_zone $binary_remote_addr zone=conname:10m;
  server {
     limit_conn conname 3;  # 每个 IP 只能发起3个连接
  }
}

例如:频率限制

http {
  limit_req_zone $binary_remtoe_addr zone=conname:1m rate=10r/s;
  server {
     limit_req zone=conname burst=5 nodelay;  # 最大请求数为5,且超过的请求不延迟
  }
}

例如:API限速

server {
   limit_rate_after 10m;  # 前10兆大小不限速
   limit_rate 100k;       # 限速为 100KB/秒
}

补充说明

内容含义
$binary_remote_addr这里填写的是限流对象,我们采用客户端IP
zone=conname给共享空间设置名称为:conname
10m空间大小:10兆
rate速率,上述表示每秒最多发起10个请求
limit_conn限制每个name对应的连接数
limit_req限制每个name对应的请求数

适配PC与移动环境

使用场景,现在的官网网站一般是分两套代码的 一套是移动端一套是PC端,这时候我们可以在nginx 进行判断

location / {
    # 移动端
    if ($http_user_agent ~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
      proxy_pass http://127.0.0.1:xxxx;
    }
    # PC端
    if ($http_user_agent !~* (mobile|nokia|iphone|ipad|android|samsung|htc|blackberry)) {
      proxy_pass http://127.0.0.1:xxxx;
    }
}

解决跨域

在nginx当中进行 反向代理

补充说明:有时候你会看有两次重复请求(options 请求,第一次是预检请求,它会先判断这次请求是否成功

解决方案:可以通过设置响应头部的 Access-Control-Max-Age 来设置预检请求有效期,即在设置的时间内只有第一次会发送出数据,下次这个接口请求(相同接口&相同参数时)不会再发出这个预检请求,而是发送真请求。

location /api/ {
  add_header ‘Access-Control-Max-Age’ 600;
  proxy_pass http://*********;
}

优雅降级

使用场景:例如在官网项目当中,ssr服务一旦出现问题,我们可以通过errer_page 做容灾处理

upstream ssr {
    server xxx max_fails=1 fail_timeout=60;
    server xxx max_fails=1 fail_timeout=60;
 }
upstream csr {
    server xxx max_fails=1 fail_timeout=60;
    server xxx max_fails=1 fail_timeout=60;
}
​
location ^~ /ssr/ {
    proxy_pass http://ssr;
    # 开启自定义错误捕获 如果这里不设置为on的话 会走向nginx处理的默认错误页面
    proxy_intercept_errors on;
    # 捕获500系列错误 如果500错误的话降级为下面的csr渲染
    error_page 500 501 502 503 504 = @csr_location
​
    # error_page 500 501 502 503 504 = 200 @csr_location
    # 注意这上面的区别 等号前面没有200 表示 最终返回的状态码已 @csr_location为准 加了200的话表示不管@csr_location返回啥都返回200状态码
}
​
location @csr_location {
    # 这时候地址还是带着/ssr/的要去除
    rewrite ^/ssr/(.*)$ /$1 break;
    proxy_pass http://csr;
    rewrite_log on;
}

权限控制

Nginx + Lua (OpenResty) 当然这个不仅仅能做权限验证,他还能去操作数据库,绕过后端服务