前端进阶之路

Nginx必备知识

2020-10-22  本文已影响0人  果汁凉茶丶

  Nginx那么神,我想去看看,走起~

Nginx 是什么?

  Nginx (engine x) 是一款由俄罗斯的程序设计师Igor Sysoev所开发的 高性能 Web和 反向代理 服务器,也是一个通用的TCP/UDP代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。
  它现在几乎是众多大型网站必备的技术,大多数情况下,对于前端的我们来说,都无需自己去配置它,但是对于了解他在应用程序中所发挥的作用及担任的角色来说,理解如何解决这些问题则是非常必要的。

Nginx有什么优势?
Nginx常用来做什么?

  打开官网,可以看到Nginx的功能有很多,对于前端开发者来说,通常掌握 HTTP的基础功能和其他HTTP功能模块中的一部分即可,如您对其他功能也感兴趣可以到官网上继续学习。前端常涉及的如下内容:


# 正向代理与反向代理

  Nginx是一台反向代理服务器,那什么是“反向代理”?
代理 就是委托、代办。在服务器和客户端之间架设的一层服务器,它负责接收客户端请求,处理完想要做的事情后,再转发给真正的服务器。不论是正向代理还是反向代理,最终实现的都是该效果,只不过是代理的对象不一样罢了。

  怎么区分正向和反向?这是一个既定的称呼。我们认为请求通过客户端发起,最终被服务端接受并处理,这么一个流向被认为是正向的流转。当代理服务器代理了客户端,充当了请求的发起方,我们称之为正向代理;相反,代理服务器代理了服务端,充当了请求接收方,隐藏了服务端,我们称之为反向代理。

正向代理

  用户知道目标服务器地址,但由于网络限制等原因(如跨域),无法直接访问。这时候需要先连接代理服务器,然后再由代理服务器访问目标服务器。这种代理方式,对服务端隐藏了真正的客户端,服务端并不知道请求是来自于代理的访问还是来自于真正的客户端访问。

  最常见的正向代理案例就是,Webpack 的 proxyTable,如下

  在这里,http://jsonplaceholder.typicode.com正是正向代理中的代理服务器,它负责收集真正客户端发起的请求并进行转发,如此一来,在服务器端收到的请求看起来均为由它发起的,从而达到了因此客户端的目的。

反向代理

  反向代理代理的是服务器,对于客户端是无感知的,甚至客户端无需做任何处理。客户端只需要将请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据后,再反馈给客户端。

  例如我们给10086打客服电话,我们只需要知道10086这个代理号码,拨通后,由哪一位客服姐姐给你服务,就是由反向代理服务器为你选择。而这个客服姐姐叫什么名字,座机号码是什么,你是不知道的。
  再比如,我们访问百度网站,我们输入www.baidu.com后,就能得到响应,但百度的服务器肯定不止一台,那是哪一台在为我们做请求处理?我们也是不知道的。

解决跨域

  对于XHR类型的请求,浏览器同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。用于隔离潜在恶意文件的重要安全机制。当存在协议,域名,访问端口三者其中之一不一致时即发生跨域。

Nginx是如何解决跨域的呢?假设
(1)前端server域名:front.server.com
(2)后端server域名:end.server.com
这种条件下,前端发起xhr请求,因为域名不一致一定会出现跨域。为解决这个问题,只需要启动一个nginx服务器,将 server_name 设置为和前端一样的域名front.server.com,然后设置相应的location用以拦截前端需要跨域的请求,最后将请求代理回后端真正的服务end.server.com即可。配置如下:

server {
  listen 80;
  server_name   front.server.com;
  location / {
    proxy_pass   end.server.com
  }
}

  这样,由前端服务器front.server.com发起的接口请求,被代理服务器以front.server.com的身份接收,保持协议与端口一致,就不会出现跨域。而代理服务器在收到请求后,再进行转发,此时已经没有浏览器参与,也就没有所谓的跨域问题,从而完成了请求的正常流转。
  你可能听着还是不太明白,具体是怎么工作的?接着往下看


# Nginx 文件配置结构

  Nginx 一个重要的功能就是反向代理,它帮助接收来自客户端的请求,执行请求转发,解决跨域,负载均衡等。他的基本配置结构如下:

用代码表示,即:

...              #main全局块

events {         #events块
   ...
}

http      #http块
{
    ...   #http全局块
    server        #server块
    { 
        ...       #server全局块
        location [PATTERN]   #location块
        {
            ...
        }
        location [PATTERN] 
        {
            ...
        }
    }
    server
    {
      ...
    }
    ...     #http全局块
}
  1. main:全局配置。配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等;
  2. events:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。
  3. http:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。
  4. server:配置虚拟主机的相关参数,一个http中可以有多个server
  5. location:配置请求的路由,以及各种页面的处理情况,如静态资源,正则路径匹配等。

# 请求分组及过滤

  Nginx的请求过滤主需要使用 location 关键字进行匹配。匹配规则如下:

符号 说明
= 对URI 做精确匹配
~ 对URI 做正则匹配,区分大小写
~* 对URI做正则匹配,不区分大小写
^~ 对URI做半部分左匹配检查,不区分字符大小写
不带符号 匹配起始于此URI的所有URL

匹配的优先级为:=、^~、~/~*、不带符号

(1)直接根据URL名称过滤,
location / {
  root /data/apps/myproject-web;
  index index.html;
  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_pass http://localhost:60001;
}

proxy_set_header用来设置请求头,以便后端获取。跟两个参数:名称 值。名称是一个可自定义的字符串,但常用的都有约定俗成的专用名词。本例中的HostX-Real-IP都是约定名

proxy_pass:设置请求转发的代理地址,这是Nginx非常重要的功能
若访问http://nginx_server/api/index.html,则设置
(1)location /api/ { proxy_pass http://localhost:60001 }代理到http://localhost:60001/api/index.html
(2)location /api/ { proxy_pass http://localhost:60001/ }代理到http://localhost:60001/index.html

  当遇到跨域问题且客户端无法支持CORS时,最好的办法就是让Nginx来做代理。在前端所在的服务器的Nginx上设置一个路由,然后使用proxy去请求另一个域名下的资源。如果前后端部署在同一台机器上,则更简单,直接使用127.0.0.1localhost加后端服务端口即可,例:

location /api {
  proxy_pass http://localhost:60001
}

  这样,当客户端请求/api这个路径下的资源时,服务器就会帮我们去localhost60001端口获取资源,完成代理解决跨域问题。
proxy_path在转发时会将$uri带过去,所以如果这个/api是我们手动加的,转发时需要去掉,则可以使用rewrite来实现

location /api/ {
  rewrite ^/api/(.*)/$1 brek;
  proxy_pass http://localhost:60001;
}

rewrite 的作用是修改 $uri,但有个副作用即重新匹配 location 。由于proxy_pass 的处理阶段比 location晚,所以需要 break 掉,以防止rewrite进入下一次location匹配而丢失proxy_pass$1表示第一个括号内匹配的正则参数。

(2)通过状态码进行过滤,使用error_page

前端关于页面丢失有两种错误:
  一种是访问的路由不存在,可在路由表最后一行配置不匹配路由的统一404页面:

{ path: '*', redirect: '/404', hidden: true }

  二是请求访问的资源不存在,此时,通过nginx来设置统一的404页面更为合适:

error_page 500 501 502 503 504 506 /50x.html;
  location = /50x.html {
    root /root/static/50x.html;
  }

error_page 404 /40x.html;
  location = /40x.html {
    root /root/static/40x.html
  }

如果需要设置自定义的响应码,则需要在code前增加等号如 error_page 401 404 =700 /40x.html

(3)根据既定条件过滤,如请求类型
if ($request_method !~ ^(GET|POST|HEAD)$  ) {
  return 403
}

$request_method是Nginx配置的一个全局变量,表示请求资源的方式。在location中常用的全局变量还有

location ~ .*\.(jpg|gif|png)$ {
    valid_referers none blocked 119.2x.1x3.218 #支持正则匹配;
    if ($invalid_referer) {
            return 403;
    }
    root /nginxtest/images;
}

# 配置压缩(gzip)

  GZIP是规定的三种标准HTTP压缩格式之一。目前绝大多数的网站都在使用GZIP传输 HTML、CSS、JavaScript 等资源文件。
  对于文本文件,gzip 的效果非常明显,开启后传输所需流量大约会降至 1/4 ~ 1/3。
  但并不是每个浏览器都支持gzip,我们可以通过请求头中的Accept-Encoding来了解浏览器是否支持gzip压缩。


  当明确浏览器支持gzip压缩后,就允许服务器返回gzip的文件,一般真正服务器很少会返回gzip文件,我们就可以通过Nginx来统一设置压缩。可以通过浏览器的response信息来观察是否已经正确开启
gzip的配置

  gzip配置在http块内部的全局变量中,针对所有的server块生效


# 负载均衡

  负载均衡是Nginx另一个非常重要的功能之一,它用来帮助我们将众多的客户端请求合理的分配到各个服务器上,以达到服务端资源充分利用和更少的请求时间。不仅如此,当其中一台服务器发生宕机时,可以将后续的请求分配给另外两台上,保证了服务的可用性。


  如上图示例,三个窗口就是需要负载的三个服务器,在Nginx中,使用upstream来配置,假设我们将负载均衡名称叫做banlanceServer,则
upstream balanceServer {
  server 10.231.5.100:60001;
  server 10.231.5.101:60001;
  server 10.231.5.102:60001;
}

那么,在server块中location节点的proxy_pass即可配置为

location / {
  root html;
  index index.html index.html;
  proxy_pass http://banlanceServer;
}
负载均衡策略选择
(1)轮询策略

  默认情况下会采用的策略,将所有客户端请求轮询分配给服务端。这种策略是可以正常工作的,但是如果其中某一台服务器压力太大,出现延迟,会影响所有分配在这台服务器下的用户。而轮询依旧会将请求分配给该服务器。

(2)最小连接数策略

  将请求优先分配给压力较小的服务器,它可以平衡每个队列的长度,并避免向压力大的服务器添加更多的请求。

upstream balanceServer {
    least_conn;
    server 10.1.22.33:12345;
    server 10.1.22.34:12345;
    server 10.1.22.35:12345;
}
(3)最快响应时间策略

  依赖于NGINX Plus,优先分配给响应时间最短的服务器。配置办法为将以上least_conn改成fair

(4)客户端IP绑定

 来自同一个ip的请求永远只分配一台服务器,有效解决了动态网页存在的session共享问题。配置办法为将以上least_conn改成ip_hash

(*)upstream其他状态值

  除了如上常规配置外,upstream还能为每一台服务器设置状态值,如下:


# 静态资源服务

  静态资源服务又叫动静分离,为了减少不必要的请求以减少资源浪费,请求延时等

location ~* \.(htm|html|js|css|png|gif|jpg|jpeg|eto|svg|ttf|woff|woff2)$ {
    root    /apps/data/static/;  
    autoindex on;
    access_log  off;
    expires     10h; # 设置过期时间为10小时          
}

  当匹配到上述后缀名文件后,直接去apps/data/static/目录下取,不向后台发请求。


# 配置https服务

  要配置https服务,需要有如下流程:
(1)申请证书,便宜ssl官网可以申请三个月免费SSL证书
(2)申请完成,下载nginx版本的证书到本地,一个crt证书文件,一个key密钥文件。
(3)配置nginx如下:

server {
  listen  443  ssl;  # 443是https的默认端口。80为http的默认端口
  sever_name  www.domain.com;  # 配置域名
  
  ssl_sertificate  证书绝对路径;
  ssl_certificate_key  密钥绝对路径;

  # locaton / {
  #   proxy_pass  http://10.213.5.100;
  # }
}

  给一个案例如下图:


  如果用户输入http://域名,默认80端口,nginx监听到80端口被访问,匹配到域名www.deram.com,将服务代理到http://192.168.3.10:8080上,服务器访问页面资源。
  如果用户输入https://二级域名,默认端口为443,nginx监听到443端口被监听,配到相应的域名,进行证书验证,将服务代理到指定服务器。

# Nginx其他配置描述

(1)全局配置

  常用的全局配置如下:

(2)event

  配置选取的驱动模型和进程最大连接数,如下:

(3)http

  http内部也有针对所有server的全局配置,本文就以下案例进行解读,更多好用的配置参见
https://www.cnblogs.com/yanshicheng/p/12673897.html


Nginx会把每个用户访问过程的 日志 信息记录到指定的日志文件里,供网站管理员分析用户浏览行为,问题定位等。和日志相关的配置主要有如下两个:

......


结束语

  Nginx的功能非常强大,也有很多复杂的用法,本文主要介绍常用的配置和知识点,欢迎指导。

上一篇 下一篇

猜你喜欢

热点阅读