二、项目中常用的Nginx配置


Nginx是一个高性能的HTTP和反向代理服务器,也是一种轻量级的Web服务器。

1. nginx在应用程序中的作用

  1. 反向代理:将来自客户端的请求转发到后端的真实服务器,然后将响应返回给客户端。以隐藏服务器的真实IP地址,提高安全性。

  2. 负载均衡:将来自客户端的请求分发到多个后端服务器,提高系统的并发处理能力

  3. gzip压缩:压缩数据,提高网络传输效率

  4. 静态资源服务器:提供对静态文件(如HTML、图片)的访问服务。并可配置缓存,以减少对后端服务器的请求次数

  5. SSL/TLS加密:对传输的数据进行加密,即HTTPS

2. 默认配置文件分析

nginx.conf 文件,即Nginx的默认配置文件

# 配置工作进程数,如果大于1,则以多进程的方式运行
worker_processes  1;

# 配置影响Nginx服务器或与用户的网络连接
events {
  # 单个工作进程可以同时打开的最大连接数
  # 最大客户端连接数由worker_processes和worker_connections决定
  worker_connections  1024;
}

# 可以嵌套多个server
http {
  # 包含其他文件到nginx.conf配置文件中,mime.types文件包含了各种文件类型
  include       mime.types;
  # 设置默认的文件类型,'application/octet-stream'是一种通用的二进制文件类型
  default_type  application/octet-stream;
  # 启用内核级别的文件传输优化
  sendfile        on;
  # 长连接时间,超过时间Nginx会关闭该连接,包括HTTP和WebSocket
  keepalive_timeout  65;

  # 配置虚拟主机的相关参数
  server {
    # 监听的端口
    listen       80;
    # 监听的域名
    # 如果写的是localhost就是代表当前服务器的ip,懂了吧
    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 默认配置文件可分为6个模块:

# 全局模块
worker_processes  1;
pid               /var/run/nginx.pid;
user              nginx;
error_log         /var/log/nginx/error.log warn;

# events模块
events {
  worker_connections  1024;
  use                 epoll;
}

# http模块
http {
  include       mime.types;
  default_type  application/octet-stream;
  sendfile      on;
  keepalive_timeout  65;

  # upstream模块
  upstream backend {
    server 192.168.1.1;
    server 192.168.1.2;
  }

  # server模块1
  server {
    listen       80;
    server_name  example.com;

    # location块1
    location / {
      root   /usr/share/nginx/html;
      index  index.html index.htm;
    }

    # location块2
    location /api {
      proxy_pass http://backend;
    }

    # 配置错误页面
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   /usr/share/nginx/html;
    }
  }

  # server模块2
  server {
    listen       80;
    server_name  another.com;

    # location块1
    location / {
      root   /var/www/another;
      index  index.html index.htm;
    }

    # location块2
    location /images {
      alias /var/www/images;
    }

    # 配置错误页面
    error_page   404  /404.html;
    location = /404.html {
      root   /var/www/another;
    }
  }

  # 可以继续添加更多的server模块和对应的location块
}

全局模块:配置影响nginx全局的指令,比如运行nginx的用户名,nginx进程pid存放路径,日志存放路径,配置文件引入,worker进程数等。

events模块:配置影响nginx服务器或与用户的网络连接。比如每个进程的最大连接数,选取哪种事件驱动模型(select/poll epoll或者是其他等等nginx支持的)来处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。

http模块:可以嵌套多个server,配置代理,缓存,日志格式定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。

server模块:配置虚拟主机的相关参数比如域名端口等等,一个http中可以有多个server。

location模块:配置url路由规则。

upstream模块:配置上游服务器的地址以及负载均衡策略和重试策略等等。

3. location 路由匹配规则

location [ = | ~ | ~* | ^~ ] uri { ... }

1. 通用匹配

通用匹配使用一个 / 表示,可以匹配所有请求。相当于 switch 中的 default。

location / {
  root   dist;
  index  index.html index.htm;
}

2. 无修饰符的前缀匹配

无修饰符的前缀匹配,匹配前缀是配置的的url

location /prefix_match {
  alias  dist;
  index  index.html index.htm;
}

提示:前缀匹配使用alias来寻找资源

匹配结果:域名/prefixmatch,域名/prefixmatch? 和域名/prefixmatch/ 这三个url能够匹配上无修饰符的前缀匹配。

# 正确匹配,重定向到其他页面
curl http://www.locatest.com/prefixmatch     ✅ 301

# 带查询参数的正确匹配,重定向到其他页面
curl http://www.locatest.com/prefixmatch?    ✅ 301

# 大写路径不匹配
curl http://www.locatest.com/PREFIXMATCH     ❌ 404

# 正确匹配,返回200状态码
curl http://www.locatest.com/prefixmatch/    ✅ 200

# 路径不匹配
curl http://www.locatest.com/prefixmatchmmm  ❌ 404

# 子路径不匹配
curl http://www.locatest.com/prefixmatch/mmm ❌ 404

# 错误的前缀路径
curl http://www.locatest.com/aaa/prefixmatch/❌ 404

3. ^~ 有修饰符的前缀匹配

# 匹配以 /exactprefixmatch 开头的请求
location ^~ /exactprefixmatch {
   [ configuration ]  # 具体配置内容
}
# 正确匹配,返回200状态码
curl http://www.locatest.com/exactprefixmatch     ✅ 200

# 带斜杠的正确匹配,返回200状态码
curl http://www.locatest.com/exactprefixmatch/    ✅ 200

# 带查询参数的正确匹配
curl http://www.locatest.com/exactprefixmatch?    ✅ 200

# 路径扩展的正确匹配
curl http://www.locatest.com/exactprefixmatchmmm  ✅ 200

# 子路径的正确匹配
curl http://www.locatest.com/exactprefixmatch/mmm ✅ 200

# 错误的前缀路径
curl http://www.locatest.com/aaa/exactprefixmatch ❌ 404

# 大写路径不匹配
curl http://www.locatest.com/EXACTPREFIXMATCH     ❌ 404

域名/exactprefixmatchmmm 和域名/exactprefixmatch/mmm 是可以匹配上的,而不带修饰符的前缀匹配这两个类型的url是匹配不上的直接返回了404。

4. = 精确匹配

location = /test {
  return 200 "hello";
}

# /test ok
# /test/ not ok
# /test2 not ok
# /test/2 not ok

5. ~ 区分大小写的正则匹配

location ~ ^/test$ {
  [ configuration ]
}

# /test ok
# /Test not ok
# /test/ not ok
# /test2 not ok

6. ~* 不区分大小写的正则匹配

location ~* ^/test$ {
  [ configuration ]
}

# /test ok
# /Test ok
# /test/ not ok
# /test2 not ok

7. 匹配优先级

优先级:

  1. 精确匹配 =

  2. 前缀匹配 ^~

  3. 正则匹配 ~ 或 ~*

  4. 通用匹配

8. root 与 alias 的区别

  1. root 是直接拼接 root + location
location /i/ {    
  root /data/w3;
}

当请求 /i/top.gif ,/data/w3/i/top.gif 会被返回。

  1. alias 是用 alias 替换 location
location /i/ {  
  alias /data/w3/images/;
}

当请求 /i/top.gif ,/data/w3/images/top.gif 会被返回

9. server 和 location 中的 root

server 和 location 中都可以使用 root,采取就近原则,如果 location 中能匹配到,就是用 location 中的 root 配置,忽略 server 中的 root,当 location 中匹配不到的时候,则使用 server 中的 root 配置

4. 解决跨域

假设页面地址:http://192.168.31.115:8080;

假设请求接口地址:

http://v.juhe.cn/laohuangli/d?date=2014-0909&key=dae46b9a6abb27fecaace80f47624f`

配置Nginx

server {
  listen       8088;  # 监听8088端口
  server_name  192.168.31.115;  # 服务器名称或IP地址

  location / {
    proxy_pass http://192.168.31.115:8080/;  # 反向代理到本地8080端口
  }

  location /laohuangli {
    proxy_pass http://v.juhe.cn/laohuangli;  # 反向代理到API
  }
}

将页面地址代理到8088端口,将接口地址也代理到8088端口

页面中请求接口

fetch('http://192.168.31.115:8088/laohuangli/d?date=2014-09-09&key=dae46b9a6abb27fecaace80f47624f')
  .then(res=>res.json())
  .then(res=>{   
    console.log(res)  
  })

访问页面:http://192.168.31.115:8088/

5. gzip压缩

http {
  gzip on; # 是否开启gzip
  gzip_min_length  1k; # 开始压缩的最小长度(再小就不要压缩了,意义不在)
  gzip_buffers     4 16k; # 缓冲(压缩在内存中缓冲几块? 每块多大?)
  gzip_http_version 1.1; # 开始压缩的http协议版本(可以不设置,目前几乎全是1.1协议)
  gzip_comp_level 2; # 推荐6 压缩级别(级别越高,压的越小,越浪费CPU计算资源)
  gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml; # 对哪些类型的文件用压缩 如txt,xml,html ,css
  gzip_vary on; # 是否传输gzip压缩标志
  gzip_proxied   expired no-cache no-store private auth; # Nginx做为反向代理的时候启用 例如如果header中包含"Expires"头信息,启用压缩
  gzip_disable   "MSIE [1-6]\."; # 正则匹配UA,配置禁用gzip条件。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
  gzip_static on; # 开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
}

6. 将HTTP请求转到HTTPS

在服务器上监听80端口,使用重定向

server {
  listen 80;
  server_name 47.101.161.174;
  return 301 https://$host$request_uri; # 永久性重定向
}

这样,如果访问http://service.com 将会跳转到 https://service.coms

7. 使用HTTP2

在监听443端口后加http2即可开启

listen 443 ssl http2;

8. 负载均衡

将请求分配给空闲服务器处理(电话号码同一个,但是不同客服接听)

upstream firstdemo {   
  server 192.168.31.123:8081;   
  server 192.168.31.123:8082;
}
server {   
  listen 8080;    
  server_name localhost;    
  location / {    
    proxy_pass http://firstdemo;  
  }}

负载均衡:upstream name {},两个server分别对应着不同的服务器

proxy_pass http://firstdemo,代理到firstdemo里两个服务器上

9. 静态资源服务器

把不常修改的静态资源文件放到nginx的静态资源目录中去,这样在访问静态资源时直接读取nginx服务器本地文件目录之后返回,这样就大大减少了后端服务的压力同时也加快了静态资源的访问速度

步骤一:在/www/server/nginx/html下创建images文件夹

步骤二:在Nginx进行配置(注意location的访问方式不同,root指定路径也不同)

server {
  listen 80;
  server_name 127.0.0.1;
  index index.html index.htm index.php;
  root /www/server/nginx/html;

  # error_page 404 /404.html;
  include enable-php.conf;

  location ^~ /images/ {
    expires 1d;
  }

  access_log /www/wwwlogs/access.log;
}

访问 http://127.0.0.1/images/1.png

实则访问:/www/server/nginx/html/images/1.png

10. 防盗链

location ~ .*\.(jpg|png|gif)$ {
   # 匹配防盗链资源的文件类型
   # 通过 valid_referers 定义合法的地址白名单
   # $invalid_referer 不合法的返回403
   valid_referers none blocked 127.0.0.1;

   if ($invalid_referer) {
       return 403;
   }
}

11. 请求限制

对于大流量恶意的访问,会造成带宽的浪费,给服务器增加压力。往往对于同一 IP 的连接数以及并发数进行限制。

关于请求限制主要有两种类型:

limit_conn_module 连接频率限制

limit_req_module 请求频率限制

# $binary_remote_addr 远程IP地址 zone 区域名称 10m内存区域大小
limit_conn_zone $binary_remote_addr zone=conn_zone:10m;

server {
  # conn_zone 设置对应的共享内存区域,1是限制的数量
  limit_conn conn_zone 1;
}

# $binary_remote_addr 远程IP地址 zone 区域名称 10m内存区域大小
# rate 为请求频率 1s 一次
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

server {
  location / {
    # 设置对应的共享内存区域
    # burst 最大请求数阈值,nodelay 不希望超过的请求被延迟
    limit_req zone=req_zone burst=5 nodelay;
  }
}

文章作者: 吴俊杰
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 吴俊杰 !
 上一篇
三、Nginx常用的基础配置 三、Nginx常用的基础配置
我一直认为nginx是介于前端后后端的中间产物,不只是后端需要会配置,前端也需要学会怎么使用,不要自己骗自己推卸责任,加油......
下一篇 
一、React Diff 算法的源码应该怎么读 一、React Diff 算法的源码应该怎么读
源码生涩难懂,但是一定要去读不要怕,要学会从战略上蔑视它,从战术上重视它,总有一天你会觉得React diff和fiber架构它并不难......
  目录